class Demo4(QDialog): # stackl = QStackedLayout() def __init__(self, parent=None): QDialog.__init__(self, parent) self.resize(400, 600) mainl = QGridLayout(self) self.stackl = QStackedLayout() self.stackl.setStackingMode(QStackedLayout.StackAll) for i in range(10): lab = QLabel(self) lab.setText('%d_label' % (i + 1)) lab.setMinimumSize(100, 100) lab.setAutoFillBackground(True) pt = lab.palette() # pt = QPalette() pt.setBrush(QPalette.Background, Qt.black) pt.setBrush(QPalette.WindowText, Qt.white) lab.setPalette(pt) lab.setAlignment(Qt.AlignCenter) self.stackl.addWidget(lab) btn = QPushButton('item:%d' % (i + 1)) mainl.addWidget(btn, i, 0) btn.clicked.connect(self.on_btnClick) mainl.addLayout(self.stackl, 0, 1, self.stackl.count(), 1) def on_btnClick(self): btn = QPushButton() i = int(self.sender().text()[len('item:'):]) - 1 print('btn:', i) self.stackl.setCurrentIndex(i)
def simple_viewer(self, add_files): """简明视图:仅包含按钮及进度条。""" # 简明视图样式:无框线,水平抬头不可见,按钮定宽,文件名列宽自适应留白 self.file_table.setColumnCount(2) row = len(self.files) + len(add_files) self.file_table.setRowCount(row) self.file_table.setShowGrid(False) self.file_table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) self.file_table.horizontalHeader().setVisible(False) self.file_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.file_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) num = 0 for inst in add_files: prog_widget = QWidget() prog_stack = QStackedLayout() prog_stack.addWidget(inst.prog) prog_stack.addWidget(inst.label) prog_stack.setStackingMode(QStackedLayout.StackAll) prog_widget.setLayout(prog_stack) inst.button.clicked.connect(functools.partial(self.del_file, inst)) inst.button.pressed.connect(self.button_pressed) inst.button.released.connect(self.button_released) index = num + len(self.files) num += 1 self.file_table.setCellWidget(index, 0, inst.button) self.file_table.setCellWidget(index, 1, prog_widget) self.files += add_files self.file_table.show() for inst in self.files: # 列表显示后再截断文件名 inst.label.setText(self.shorten_filename(inst.name, self.file_table.columnWidth(1)))
def __init__(self, widget_idx): super().__init__() self.__widget_idx = widget_idx v_box = QVBoxLayout(self) v_box.setSpacing(0) v_box.setContentsMargins(0, 0, 0, 0) self.__img_holder = QLabel(self) self.__img_holder.setStyleSheet("QLabel { border: 0px;}") self.__label_holder = QLabel(text='?') self.__label_holder.setStyleSheet( "QLabel { background-color : rgb(200, 200, 200); color : black; border: 0px;}" ) self.__label_holder.setAlignment(Qt.AlignCenter) self.__sn_holder = QLabel(text='00000') self.__sn_holder.setAlignment(Qt.AlignTop) self.__sn_holder.setStyleSheet( "QLabel { background-color : rgb(0, 0, 0, 128); color : white; border: 0px;}" ) br = self.__sn_holder.fontMetrics().boundingRect('00000') self.__sn_holder.setFixedSize(br.width(), br.height()) stackedLayout = QStackedLayout() # Stack image and sn, label stackedLayout.setStackingMode( QStackedLayout.StackAll) # All widgets are visible stackedLayout.addWidget(self.__img_holder) stackedLayout.addWidget(self.__sn_holder) v_box.addLayout(stackedLayout) v_box.addWidget(self.__label_holder)
class ResultPanel(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.messageLabel = QLabel() self.messageLabel.setObjectName('messageLabel') self.messageLabel.setTextInteractionFlags(Qt.TextSelectableByMouse) self.messageLabel.setWordWrap(True) self.messageLabel.setScaledContents(True) self.messageLabel.setAlignment(Qt.AlignTop) self.iconLabel = QLabel() self.iconLabel.setAttribute(Qt.WA_TransparentForMouseEvents, True) self.iconLabel.setAlignment(Qt.AlignRight) self.layout = QStackedLayout(self) self.layout.setStackingMode(QStackedLayout.StackAll) self.layout.addWidget(self.iconLabel) self.layout.addWidget(self.messageLabel) self.setLayout(self.layout) shadow = QGraphicsDropShadowEffect(self) shadow.setColor(Qt.black) shadow.setBlurRadius(10) shadow.setOffset(0, 0) self.setGraphicsEffect(shadow) self.hide()
def __init__(self): super(LoginView, self).__init__() self.resize(476, 200) stack_layout = QStackedLayout(self) stack_layout.setStackingMode(QStackedLayout.StackAll) stack_layout.addChildWidget(UICreatetor.create_background()) content = self.create_login_content() content.move( self.width()-content.width() >> 1, self.height()-content.height() >> 1 ) stack_layout.addChildWidget(content) self.msg_alert = QLabel("密码不能为空") self.msg_alert.setStyleSheet("background-color: rgb(242, 206, 58);" "color: rgb(80, 80, 80);font: 12pt \"Microsoft YaHei UI\";") self.msg_alert.resize(476, 30) self.msg_alert.setAlignment(Qt.AlignCenter) self.msg_alert.move(0, 200) stack_layout.addChildWidget(self.msg_alert) self.alert_anim_in = QPropertyAnimation(self.msg_alert, b"pos") self.alert_anim_in.setStartValue(QPoint(0, 200)) self.alert_anim_in.setEndValue(QPoint(0, 200)) self.alert_anim_in.setEasingCurve(QEasingCurve.OutBack) self.alert_anim_in.setKeyValueAt(0.05, QPoint(0, 170)) self.alert_anim_in.setKeyValueAt(0.95, QPoint(0, 170)) self.alert_anim_in.setDuration(8000) self.anim_in = QPropertyAnimation(self, b"pos") self.anim_out = QPropertyAnimation(self, b"pos") self.anim_in.setStartValue(QPoint(2, 0)) self.anim_in.setEndValue(QPoint(2, 200)) self.anim_in.setKeyValueAt(0.5, QPoint(2, 0)) self.anim_in.setEasingCurve(QEasingCurve.InOutBounce) self.anim_in.setDuration(2000) self.anim_out.setDuration(500) self.anim_out.setStartValue(QPoint(2, 200)) self.anim_out.setEndValue(QPoint(2, 0)) self.anim_out.setEasingCurve(QEasingCurve.OutExpo) if os.path.exists("ac.bin"): with open("ac.bin", "r") as file: content = file.read() dec_str = LoginTool.decrypt(content) print(dec_str) dec_str = dec_str.replace("\x00", "") ups = dec_str.split("|") print(ups,len(ups)) if len(ups) == 2: self.username_edit.setText(ups[0]) self.password_edit.setText(ups[1]) file.close() else: print("密码文件不存在")
def detail_viewer(self, add_files): """详细视图:包括按钮、进度条、详细进度、文件大小、状态""" self.file_table.setColumnCount(5) row = len(self.files) + len(add_files) self.file_table.setRowCount(row) self.file_table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) self.file_table.setHorizontalHeaderLabels(['', '文件名', '传输进度', '文件大小', '状态']) # 要用表头的ResizeMode函数而不能用列的ResizeMode函数,否则表头仍可拖动 self.file_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) self.file_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) num = 0 for inst in add_files: prog_stack = QStackedLayout() prog_stack.addWidget(inst.prog) prog_stack.addWidget(inst.label) prog_stack.setStackingMode(QStackedLayout.StackAll) prog_widget = QWidget() prog_widget.setLayout(prog_stack) # 定义按钮点击删除,长按清空的行为 inst.button.clicked.connect(functools.partial(self.del_file, inst)) inst.button.pressed.connect(self.button_pressed) inst.button.released.connect(self.button_released) file_prog = QTableWidgetItem('0.00 %') file_prog.setTextAlignment(Qt.AlignCenter) file_size = QTableWidgetItem(inst.size) file_size.setTextAlignment(Qt.AlignCenter) file_status = QTableWidgetItem(inst.status[1]) file_status.setTextAlignment(Qt.AlignCenter) index = num + len(self.files) num += 1 self.file_table.setCellWidget(index, 0, inst.button) self.file_table.setCellWidget(index, 1, prog_widget) self.file_table.setItem(index, 2, file_prog) self.file_table.setItem(index, 3, file_size) self.file_table.setItem(index, 4, file_status) self.files += add_files self.file_table.show() row_height = self.file_table.rowHeight(0) * self.file_table.rowCount() header_height = self.file_table.horizontalHeader().height() if row_height + header_height >= self.file_table.height(): # 计算是否出现滚动条 for inst in self.files: changed_text = self.shorten_filename(inst.name, self.file_table.columnWidth(1) - self.reso_width / 192) inst.label.setText(changed_text) else: for inst in self.files: changed_text = self.shorten_filename(inst.name, self.file_table.columnWidth(1)) inst.label.setText(changed_text)
def _makeCaptionLayout(k): extracaptions = k.data.get("extracaptions", None) if not extracaptions: return False # ecl = extra captions layout ecl = QStackedLayout() ecl.setStackingMode(QStackedLayout.StackAll) ecl.addWidget(k) for cssclass, txt in extracaptions.items(): ql = QLabel(txt) ql.setProperty("class", cssclass) ql.setAttribute(Qt.WA_TransparentForMouseEvents) ecl.addWidget(ql) return ecl
class CalculatorUnitWidget(UnitWidget, UniversalUniqueIdentifiable): def __init__(self, unit_view, parent=None, size=32): super(CalculatorUnitWidget, self).__init__(unit_view, parent, size) # Setup card layout self.card_widget = QWidget(self) self.cardLayout = QHBoxLayout() for idx, card in enumerate(self.cards): card.setMinimumSize(QSize(self.size + 2, self.size + 2)) self.cardLayout.addWidget(card) self.card_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.card_widget.setLayout(self.cardLayout) # Setup overlay self.label = QLabel(self.card_widget) self.label.setText("Running...") font = QFont() font.setPixelSize(20) self.label.setFont(font) self.label.setAlignment(Qt.AlignCenter) self.label.setStyleSheet("background-color: rgba(255, 255, 255, 100);") self.label.setAutoFillBackground(True) self.stacked_layout = QStackedLayout() self.stacked_layout.addWidget(self.card_widget) self.stacked_layout.addWidget(self.label) self.stacked_layout.setContentsMargins(0, 0, 0, 0) self.stacked_layout.setStackingMode(QStackedLayout.StackAll) self.setLayout(self.stacked_layout) self.toggle_running_simulation(False) self.running_simulation = False def toggle_running_simulation(self, running=False): self.label.setVisible(running) self.running_simulation = running def handle_lost_mime(self, mime_text): if type(self.unit_view) == UnitView: self.unit_view.handle_lost_mime(mime_text)
def ui(self): if self.layout(): QWidget().setLayout(self.layout()) self.setMinimumWidth(self.width) self.setMaximumWidth(self.width) self.setMinimumHeight(self.height) self.setMaximumHeight(self.height) _main_layout = QStackedLayout() _main_layout.setContentsMargins(0, 0, 0, 0) # _main_layout.setAlignment(Qt.AlignHCenter | Qt.AlignTop) _main_layout.setStackingMode(QStackedLayout.StackAll) background = QLabel() pix = QtGui.QPixmap(self.path) pix = pix.scaled(self.width, self.height) background.setPixmap(pix) mylayout = QVBoxLayout() title = QLabel(self.title) title.setObjectName('title') subtitle = QLabel(self.subtitle) subtitle.setObjectName('subtitle') subtitle.setMaximumWidth(self.width / 2) subtitle.setWordWrap(True) # 短横线 line = HorizontalLine(color="white", wid=10) line.setMaximumWidth(58) line.setObjectName('line') mylayout.addWidget(title) mylayout.addWidget(subtitle) mylayout.addWidget(line) wid = QWidget() wid.setStyleSheet('background: transparent') wid.setLayout(mylayout) _main_layout.addWidget(background) _main_layout.addWidget(wid) return _main_layout
def initUI(self): ## Information Labels: infoLabel1 = QLabel() ## NAME infoLabel1.setText(con[self.conNum - 1][0][0]["name"].upper()) infoLabel1.setFont(QFont(fonts[1], rPix(25), weight=75)) infoLabel2 = QLabel() infoLabel2.setText(con[self.conNum - 1][1][0]["name"].upper()) infoLabel2.setFont(QFont(fonts[1], rPix(25), weight=75)) infoLabel3 = QLabel() ## SECTION if con[self.conNum - 1][0][1]["section"] == con[self.conNum - 1][1][1]["section"]: infoLabel3.setText( str(con[self.conNum - 1][2]["grade"]) + " - " + con[self.conNum - 1][0][1]["section"]) else: infoLabel3.setText( str(con[self.conNum - 1][2]["grade"]) + " - " + con[self.conNum - 1][0][1]["section"] + " & " + con[self.conNum - 1][1][1]["section"]) infoLabel3.setFont(QFont(fonts[0], rPix(15), weight=75)) infoLabelLayout = [QHBoxLayout(), QHBoxLayout(), QHBoxLayout() ] ## Centralize Using Horizontal Box Layout for i in infoLabelLayout: i.setContentsMargins(0, 0, 0, 0) i.setSpacing(0) infoLabelLayout[0].addStretch() infoLabelLayout[0].addWidget(infoLabel1) infoLabelLayout[0].addStretch() infoLabelLayout[1].addStretch() infoLabelLayout[1].addWidget(infoLabel2) infoLabelLayout[1].addStretch() infoLabelLayout[2].addStretch() infoLabelLayout[2].addWidget(infoLabel3) infoLabelLayout[2].addStretch() ## Information Layout: infoLayout = QVBoxLayout() infoLayout.setSpacing(10) for i in infoLabelLayout: infoLayout.addLayout(i) ## Information Frame: infoFrame = QFrame() infoFrame.setFixedSize(rPix(780), rPix(205)) infoFrame.setObjectName("infoFrame") infoFrame.setStyleSheet( ".QFrame#infoFrame{border-bottom:2px #A9A9A9;background:" + self.ui[(self.conNum - 1) % 4] + ";border-radius : 5px}") infoFrame.setLayout(infoLayout) ## Score Sheet Webview: if "-nosheet" in sys.argv: self.sheet = QFrame() self.sheet.setFixedSize(rPix(760), rPix(630)) else: self.sheet = QWebView() self.sheet.loadFinished.connect(self.pageLoaded) _path = QUrl.fromLocalFile(currentDir() + "/resources/sheet.html") self.sheet.load(_path) ## Navigation Buttons resetButton = ImageButton("resources/img/buttons/reset", rPix(30), rPix(30), toggle=False, tooltip="<b>Reset Scores</b>") saveButton = ImageButton("resources/img/buttons/save", rPix(30), rPix(30), toggle=False, tooltip="<b>Save Scores</b>") if "-nosheet" not in sys.argv: resetButton.clicked.connect(self.resetScores) saveButton.clicked.connect(self.saveScores) ## Sheet Navigation Layout: sheetNavigationLayout = QHBoxLayout() sheetNavigationLayout.addStretch() sheetNavigationLayout.addWidget(resetButton) sheetNavigationLayout.addWidget(saveButton) ## Layout of Sheet Frame: sheetLayout = QVBoxLayout() sheetLayout.setContentsMargins(rPix(15), rPix(10), rPix(10), rPix(10)) sheetLayout.setSpacing(rPix(5)) sheetLayout.addWidget(self.sheet) sheetLayout.addLayout(sheetNavigationLayout) ## Sheet Frame: sheetFrame = QFrame() sheetFrame.setFixedSize(rPix(780), rPix(650)) sheetFrame.setObjectName("sheetFrame") sheetFrame.setStyleSheet( ".QFrame#sheetFrame{border-bottom:2px #A9A9A9;background:" + self.ui[(self.conNum - 1) % 4] + ";border-radius : 5px}") sheetFrame.setLayout(sheetLayout) ## Left Placeholder Layout: leftLayout = QVBoxLayout() leftLayout.setContentsMargins(0, 0, 0, 0) leftLayout.setSpacing(10) leftLayout.addWidget(infoFrame) leftLayout.addWidget(sheetFrame) ## Previous Image Button: prevImage = ImageButton("resources/img/buttons/prevImg", rPix(100), rPix(845), toggle=False, tooltip="<b>Previous Image</b>") prevImage.clicked.connect(self.prevImageEvt) ## Next Image Button: nextImage = ImageButton("resources/img/buttons/nextImg", rPix(100), rPix(845), toggle=False, tooltip="<b>Next Image</b>") nextImage.clicked.connect(self.nextImageEvt) ##Con Num Label: conNumLabel = QLabel(str(self.conNum)) conNumLabel.setFont(QFont(fonts[0], rPix(30))) ##Con Num Layout: conNumLabelLayout = QHBoxLayout() conNumLabelLayout.setContentsMargins(0, 0, 0, 0) conNumLabelLayout.setSpacing(0) conNumLabelLayout.addStretch() conNumLabelLayout.addWidget(conNumLabel) conNumLabelLayout.addStretch() ## Label for info self.infoconLabel = QLabel("NO IMAGE LOADED") self.infoconLabel.setFont(QFont(fonts[1], rPix(10))) ##Con Num Layout: infoconLabelLayout = QHBoxLayout() infoconLabelLayout.setContentsMargins(0, 0, 0, 0) infoconLabelLayout.setSpacing(0) infoconLabelLayout.addStretch() infoconLabelLayout.addWidget(self.infoconLabel) infoconLabelLayout.addStretch() ##Vertical Layout for conNum and Info vertConInfoLayout = QVBoxLayout() vertConInfoLayout.setContentsMargins(0, 0, 0, 0) vertConInfoLayout.setSpacing(rPix(20)) vertConInfoLayout.addStretch() vertConInfoLayout.addLayout(conNumLabelLayout) vertConInfoLayout.addLayout(infoconLabelLayout) vertConInfoLayout.addStretch() ## Image Info Frame: infoFrame = ImageFrame() _infoPixmap = QPixmap("resources/img/infoFrame.png") infoFrame.setPixmap( _infoPixmap.scaled(rPix(560), rPix(120), Qt.KeepAspectRatio)) infoFrame.setLayout(vertConInfoLayout) ## Image Info Filler: infoFiller = QLabel() infoFiller.setFixedSize(rPix(560), rPix(727)) ## Image Info Layout: infoLayout = QVBoxLayout() infoLayout.addWidget(infoFiller) infoLayout.addWidget(infoFrame) infoLayout.setContentsMargins(0, 0, 0, 0) infoLayout.setSpacing(0) ## Image Navigation/Info Layout: navigLayout = QHBoxLayout() navigLayout.addWidget(prevImage) navigLayout.addLayout(infoLayout) navigLayout.addWidget(nextImage) navigLayout.setContentsMargins(0, 0, 0, 0) navigLayout.setSpacing(0) ## Image Navigation/Info Frame: navigFrame = QFrame() navigFrame.setObjectName("noframe") navigFrame.setStyleSheet(styles["noframe"]) navigFrame.setLayout(navigLayout) ## Image Frame: self.imageFrame = ImageFrame(fade=True) try: ##Checks if Pixmap is available, then sets it self.imageFrame.setPixmap(self.pixmaps[str( self.conNum)][self.imgNum]) self.infoconLabel.setText(order[self.imgNum]) except: pass self.imageFrame.setFixedSize(rPix(760), rPix(845)) #self.imageFrame.setLayout(navigLayout) ## Image Stacked Layout: imageStacked = QStackedLayout() imageStacked.setStackingMode(QStackedLayout.StackAll) imageStacked.setContentsMargins(0, 0, 0, 0) imageStacked.setSpacing(0) imageStacked.insertWidget(0, self.imageFrame) imageStacked.insertWidget(1, navigFrame) ## Image Placeholder Layout: imagePlaceholderLayout = QHBoxLayout() imagePlaceholderLayout.setContentsMargins(rPix(15), rPix(10), rPix(10), rPix(10)) imagePlaceholderLayout.setSpacing(0) imagePlaceholderLayout.addLayout(imageStacked) ## Image Placeholder Frame imagePlaceholderFrame = QFrame() imagePlaceholderFrame.setObjectName("imageplaceholder") imagePlaceholderFrame.setStyleSheet( ".QFrame#imageplaceholder{border-bottom:2px #A9A9A9;background:" + self.ui[(self.conNum - 1) % 4] + ";border-radius : 5px}") imagePlaceholderFrame.setFixedSize(rPix(780), rPix(865)) imagePlaceholderFrame.setLayout(imagePlaceholderLayout) ## Main Layout: mainLayout = QHBoxLayout() mainLayout.setContentsMargins(rPix(10), rPix(10), rPix(10), rPix(10)) mainLayout.setSpacing(10) ## Dynamic Layouting (based on Contestant Number) if self.conNum <= (tconNum / 2): mainLayout.addLayout(leftLayout) mainLayout.addWidget(imagePlaceholderFrame) else: mainLayout.addWidget(imagePlaceholderFrame) mainLayout.addLayout(leftLayout) ## Background Frame: mainFrame = ImageFrame() mainFrame.setPixmap(self.bg) mainFrame.setLayout(mainLayout) ## Placeholder Layout: placeholderLayout = QHBoxLayout() placeholderLayout.setContentsMargins(0, 0, 0, 0) placeholderLayout.setSpacing(0) placeholderLayout.addWidget(mainFrame) self.setLayout(placeholderLayout)
def __init__(self, parent, title="Title", width=500, height=180): self.parent = parent self.dragPosition = None self.width = width self.height = height super().__init__(parent) self.setWindowFlags(Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground) self.gap = 10 self.center(self.width + self.gap, self.height + self.gap) self.setAcceptDrops(True) layout = QVBoxLayout() layout.setSpacing(0) layout.setAlignment(Qt.AlignTop) layout.setContentsMargins(0, 0, 0, 0) # Title title = QLabel(title) title.setObjectName('title') def trigger_close(_): self.close() close_btn = Builder().text('x').name('close_btn').click( trigger_close).build() header = QHBoxLayout() header.addWidget(title) header.addStretch(1) header.addWidget(close_btn) self.close_btn = close_btn dlgHeader = QFrame() dlgHeader.setObjectName('header') dlgHeader.setMaximumWidth(width) dlgHeader.setLayout(header) layout.addWidget(dlgHeader) widget = QWidget(self) self.main = self.ui(widget) widget.setObjectName('main') widget.setLayout(self.main) widget.setMaximumWidth(width) layout.addWidget(widget) _main = QWidget() _main.setContentsMargins(0, 0, 0, 10) _main.setLayout(layout) _main.setStyleSheet(self.style()) _main.setWindowOpacity(0.5) _main_layout = QStackedLayout() _main_layout.setContentsMargins(20, 20, 20, 20) _main_layout.setAlignment(Qt.AlignCenter) _main_layout.setStackingMode(QStackedLayout.StackAll) _backgound = QFrame() _backgound.setMinimumWidth(width) _backgound.setMinimumHeight(height) _backgound.setMaximumWidth(width) _backgound.setMaximumHeight(height) _backgound.setStyleSheet("background: #fafafa; border-radius:5px;") if not app.is_windows(): _main_layout.addWidget(_backgound) _main_layout.addWidget(_main) self.setLayout(_main_layout) self.effect = QGraphicsDropShadowEffect(_backgound) self.effect.setOffset(0, 0) self.effect.setBlurRadius(30) # self.effect.setEnabled(False) _backgound.setGraphicsEffect(self.effect)
class _MainContainer(QWidget): ############################################################################### # MainContainer SIGNALS ############################################################################### """ newFileOpened(QString) allTabClosed() runFile(QString) addToProject(QString) showFileInExplorer(QString) recentTabsModified() currentEditorChanged(QString) fileOpened(QString) ---------migrationAnalyzed() findOcurrences(QString) ---------updateFileMetadata() editorKeyPressEvent(QEvent) locateFunction(QString, QString, bool) [functionName, filePath, isVariable] updateLocator(QString) beforeFileSaved(QString) fileSaved(QString) openPreferences() --------openProject(QString) ---------dontOpenStartPage() """ newFileOpened = pyqtSignal(str) allTabClosed = pyqtSignal() runFile = pyqtSignal(str) addToProject = pyqtSignal(str) showFileInExplorer = pyqtSignal(str) recentTabsModified = pyqtSignal() currentEditorChanged = pyqtSignal(str) fileOpened = pyqtSignal(str) migrationAnalyzed = pyqtSignal()#----------- findOcurrences = pyqtSignal(str) updateFileMetadata = pyqtSignal()#----------- editorKeyPressEvent = pyqtSignal('QEvent*') locateFunction = pyqtSignal(str, str, bool) updateLocator = pyqtSignal(str) beforeFileSaved = pyqtSignal(str) fileSaved = pyqtSignal(str) openPreferences = pyqtSignal() openProject = pyqtSignal(str)#----------- dontOpenStartPage = pyqtSignal()#----------- closeDialog = pyqtSignal('QObject*') allTabsClosed = pyqtSignal() splitEditor = pyqtSignal('QWidget*', 'QWidget*', bool) closeSplit = pyqtSignal(QWidget) toRemovePreview = pyqtSignal() ############################################################################### def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) # self._files_handler = files_handler.FilesHandler(self) self._add_file_folder = add_file_folder.AddFileFolderWidget(self) self.tdir = None #documentation browser self.docPage = None #Code Navigation self._locator = locator.GoToDefinition() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.locateFunction.connect(self.locate_function) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile',#(QString) 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition',#(int) 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'pep8Activated',#(bool) 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated',#(bool) 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) self.selector = main_selector.MainSelector(self) self._opening_dialog = False self.add_widget(self.selector) if settings.SHOW_START_PAGE: self.show_start_page() self.selector.changeCurrent[int].connect(self._change_current_stack) self.selector.removeWidget[int].connect(self._remove_item_from_stack) self.selector.ready.connect(self._selector_ready) self.selector.closePreviewer.connect(self._selector_Close) self.selector.animationCompleted.connect(self._selector_animation_completed) self.closeDialog.connect(self.remove_widget) self.stack.widgetRemoved[int].connect(lambda i:print("widgetRemoved._-", i)) def install(self): ide = IDE.getInstance() ide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.combo_area.allFilesClosed.connect(self._files_closed) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) self.current_widget = self.combo_area ui_tools.install_shortcuts(self, actions.ACTIONS, ide) def add_status_bar(self, status): self._vbox.addWidget(status) @property def combo_header_size(self): return self.combo_area.bar.height() def add_widget(self, widget): i = self.stack.addWidget(widget) #if not isinstance(widget, start_page.StartPage): self.tryMakeImagePreview(i) def remove_widget(self, widget): #self.toRemovePreview.emit(self.stack.widget(widget)) self.stack.removeWidget(widget) def _close_dialog(self, widget): self.closeDialog.emit(widget) widget.finished[int].disconnect()#lambda i: self._close_dialog(widget)) def show_dialog(self, widget): print("\n\nshow_dialog", self.isVisible()) self._opening_dialog = True widget.finished[int].connect(lambda i: self._close_dialog(widget)) widget.setVisible(True) self.show_selector() def show_selector(self): print("\n\nshow_selector::", self.selector, self.stack.currentWidget()) if self.selector != self.stack.currentWidget(): _dir = self.Successful_Tmp() if not _dir: print("failed!") return # temp_dir = os.path.join(QDir.tempPath(), "ninja-ide") # if not os.path.exists(temp_dir): # os.mkdir(temp_dir) collected_data = [] current = self.stack.currentIndex() for index in range(self.stack.count()): widget = self.stack.widget(index) if widget == self.selector: continue closable = True if widget == self.splitter: closable = False # path = os.path.join(temp_dir, "screen%s.png" % index) #ff = QFile(_dir, "screen%s.png" % index) path = _dir.absolutePath()+"/screen%s.png" % index pixmap = widget.grab()#widget.rect()) pixmap.save(path) #path = path.replace("\\", '/') #print("path::", path, QFileInfo(path).exists()) path = "file:///"+path if index == current: self.selector.set_preview(index, path)#QUrl(path) collected_data.insert(0, (index, path, closable)) else: collected_data.append((index, path, closable)) self.selector.set_model(collected_data) print("self.selector.set_model()", collected_data) self.stack.setCurrentWidget(self.selector) else: print("\n\n_selector_Close()") self._selector_Close() def Successful_Tmp(self):# CheckTmpDir, StateTmpDir failed = lambda: not self.tdir or not self.tdir.isValid() if failed():# not successfully self.tdir = QTemporaryDir() if failed(): QMessageBox.critical(self, "Unexpected Failurer", "The application has detected a problem trying to\nCreate or Access a Temporary File!.") return None else: self.tdir.setAutoRemove(True) d = QDir(self.tdir.path()) if not d.exists("ninja-ide"): if not d.mkdir("ninja-ide"): self.tdir = None d.cd("ninja-ide") return d def tryMakeImagePreview(self, index): return d = self.Successful_Tmp() if d: self.makeImagePreview(d, index) def makeImagePreview(self, _dir, index): return path = _dir.absolutePath()+"/screen%s.png" % index widget = self.stack.widget(index) pixmap = widget.grab()#widget.rect() pixmap.save(path) def _selector_ready(self): self.stack.setCurrentWidget(self.selector) self.selector.GoTo_GridPreviews() def _selector_Close(self): self.stack.setCurrentWidget(self.splitter) def _selector_animation_completed(self): if self._opening_dialog: # We choose the last one with -2, -1 (for last one) + # -1 for the hidden selector widget which is in the stacked too. self.selector.open_item(self.stack.count() - 2) self._opening_dialog = False def _change_current_stack(self, index): self.stack.setCurrentIndex(index) def _remove_item_from_stack(self, index): #self.toRemovePreview.emit(index) widget = self.stack.takeAt(index) del widget def show_editor_area(self): self.stack.setCurrentWidget(self.splitter) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def change_visibility(self): """Show/Hide the Main Container area.""" print("change_visibility11") if self.isVisible(): self.hide() else: self.show() def expand_symbol_combo(self): self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_symbol() def expand_file_combo(self): print("expand_file_combo") self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_file() def locate_function(self, function, filePath, isVariable): """Move the cursor to the proper position in the navigate stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.file_path, editorWidget.getCursorPosition())) self.__codeForward = [] self._locator.navigate_to(function, filePath, isVariable) def run_file(self, path): self.runFile.emit(path) def _add_to_project(self, path): self.addToProject.emit(path) def _show_file_in_explorer(self, path): self.showFileInExplorer.emit(path) def paste_history(self): """Paste the text from the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): line, index = editorWidget.getCursorPosition() central = IDE.get_service('central_container') if central: editorWidget.insertAt(central.get_paste(), line, index) def copy_history(self): """Copy the selected text into the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): copy = editorWidget.selectedText() central = IDE.get_service('central_container') if central: central.add_copy(copy) def import_from_everywhere(self): """Insert an import line from any place in the editor.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def add_back_item_navigation(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.file_path, editorWidget.getCursorPosition())) self.__codeForward = [] def preview_in_browser(self): """Load the current html file in the default browser.""" editorWidget = self.get_current_editor() if editorWidget: if not editorWidget.file_path: self.save_file() ext = file_manager.get_file_extension(editorWidget.file_path) if ext in ('html', 'shpaml', 'handlebars', 'tpl'): webbrowser.open_new_tab(editorWidget.file_path) def add_bookmark_breakpoint(self): """Add a bookmark or breakpoint to the current file in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): if self.current_widget.bar.code_navigator.operation == 1: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.ControlModifier) elif self.current_widget.bar.code_navigator.operation == 2: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.NoModifier) def __navigate_with_keyboard(self, val): """Navigate between the positions in the jump history stack.""" op = self.current_widget.bar.code_navigator.operation self.navigate_code_history(val, op) def navigate_code_history(self, val, op): """Navigate the code history.""" self.__operations[op](val) def _navigate_code_jumps(self, val): """Navigate between the jump points.""" node = None if not val and self.__codeBack: node = self.__codeBack.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeForward.append((editorWidget.file_path, editorWidget.getCursorPosition())) elif val and self.__codeForward: node = self.__codeForward.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.file_path, editorWidget.getCursorPosition())) if node: filename = node[0] line, col = node[1] self.open_file(filename, line, col) def _navigate_breakpoints(self, val): """Navigate between the breakpoints.""" #FIXME: put navigate breakpoints and bookmarks as one method. breakList = list(settings.BREAKPOINTS.keys()) breakList.sort() if not breakList: return if self.__breakpointsFile not in breakList: self.__breakpointsFile = breakList[0] index = breakList.index(self.__breakpointsFile) breaks = settings.BREAKPOINTS.get(self.__breakpointsFile, []) lineNumber = 0 #val == True: forward if val: if (len(breaks) - 1) > self.__breakpointsPos: self.__breakpointsPos += 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: if index < (len(breakList) - 1): self.__breakpointsFile = breakList[index + 1] else: self.__breakpointsFile = breakList[0] self.__breakpointsPos = 0 lineNumber = settings.BREAKPOINTS[self.__breakpointsFile][0] else: if self.__breakpointsPos > 0: self.__breakpointsPos -= 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: self.__breakpointsFile = breakList[index - 1] breaks = settings.BREAKPOINTS[self.__breakpointsFile] self.__breakpointsPos = len(breaks) - 1 lineNumber = breaks[self.__breakpointsPos] if file_manager.file_exists(self.__breakpointsFile): self.open_file(self.__breakpointsFile, lineNumber, None, True) else: settings.BREAKPOINTS.pop(self.__breakpointsFile) if settings.BREAKPOINTS: self._navigate_breakpoints(val) def _navigate_bookmarks(self, val): """Navigate between the bookmarks.""" bookList = list(settings.BOOKMARKS.keys()) bookList.sort() if not bookList: return if self.__bookmarksFile not in bookList: self.__bookmarksFile = bookList[0] index = bookList.index(self.__bookmarksFile) bookms = settings.BOOKMARKS.get(self.__bookmarksFile, []) lineNumber = 0 #val == True: forward if val: if (len(bookms) - 1) > self.__bookmarksPos: self.__bookmarksPos += 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: if index < (len(bookList) - 1): self.__bookmarksFile = bookList[index + 1] else: self.__bookmarksFile = bookList[0] self.__bookmarksPos = 0 lineNumber = settings.BOOKMARKS[self.__bookmarksFile][0] else: if self.__bookmarksPos > 0: self.__bookmarksPos -= 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: self.__bookmarksFile = bookList[index - 1] bookms = settings.BOOKMARKS[self.__bookmarksFile] self.__bookmarksPos = len(bookms) - 1 lineNumber = bookms[self.__bookmarksPos] if file_manager.file_exists(self.__bookmarksFile): self.open_file(self.__bookmarksFile, lineNumber, None, True) else: settings.BOOKMARKS.pop(self.__bookmarksFile) if settings.BOOKMARKS: self._navigate_bookmarks(val) def count_file_code_lines(self): """Count the lines of code in the current file.""" editorWidget = self.get_current_editor() if editorWidget: block_count = editorWidget.lines() blanks = re.findall('(^\n)|(^(\s+)?#)|(^( +)?($|\n))', editorWidget.text(), re.M) blanks_count = len(blanks) resume = self.tr("Lines code: %s\n") % (block_count - blanks_count) resume += (self.tr("Blanks and commented lines: %s\n\n") % blanks_count) resume += self.tr("Total lines: %s") % block_count msgBox = QMessageBox(QMessageBox.Information, self.tr("Summary of lines"), resume, QMessageBox.Ok, editorWidget) msgBox.exec_() def editor_cut(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.cut() def editor_copy(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.copy() def editor_paste(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.paste() def editor_upper(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_upper() def editor_lower(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_lower() def editor_title(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_title() def editor_go_to_definition(self): """Search the definition of the method or variable under the cursor. If more than one method or variable is found with the same name, shows a table with the results and let the user decide where to go.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.go_to_definition() def editor_redo(self): """Execute the redo action in the current editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.redo() def editor_undo(self): editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.undo() def editor_indent_less(self): """Indent 1 position to the left for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_less() def editor_indent_more(self): """Indent 1 position to the right for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_more() def editor_insert_debugging_prints(self): """Insert a print statement in each selected line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_debugging_prints(editorWidget) def editor_insert_pdb(self): """Insert a pdb.set_trace() statement in tjhe current line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_pdb(editorWidget) def editor_comment(self): """Mark the current line or selection as a comment.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.comment(editorWidget) def editor_uncomment(self): """Uncomment the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.uncomment(editorWidget) def editor_insert_horizontal_line(self): """Insert an horizontal lines of comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_horizontal_line(editorWidget) def editor_insert_title_comment(self): """Insert a Title surrounded by comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_title_comment(editorWidget) def editor_remove_trailing_spaces(self): """Remove the trailing spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.remove_trailing_spaces(editorWidget) def editor_replace_tabs_with_spaces(self): """Replace the Tabs with Spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.replace_tabs_with_spaces(editorWidget) def editor_move_up(self): """Move the current line or selection one position up.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_up(editorWidget) def editor_move_down(self): """Move the current line or selection one position down.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_down(editorWidget) def editor_remove_line(self): """Remove the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.remove_line(editorWidget) def editor_duplicate(self): """Duplicate the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.duplicate(editorWidget) def editor_highlight_word(self): """Highlight the occurrences of the current word in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.highlight_selected_word() def editor_complete_declaration(self): """Do the opposite action that Complete Declaration expect.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.complete_declaration() def editor_go_to_line(self, line, select=False):#def editor_go_to_line(self, line): """Jump to the specified line in the current editor.""" editorWidget = self.get_current_editor() print("\nluego en segundo lugar por aca") if editorWidget: editorWidget.jump_to_line(line)#select def editor_go_to_symbol_line(self, line, sym= "", select=False): """Jump to the specified line in the current editor.""" editorWidget = self.get_current_editor() print("\nluego en segundo lugar por aca") if editorWidget: editorWidget.go_to_symbol(line, sym, select)#select def zoom_in_editor(self): """Increase the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_in() def zoom_out_editor(self): """Decrease the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_out() def recent_files_changed(self): self.recentTabsModified.emit() def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): # file_path = event.mimeData().urls()[0].toLocalFile() # paths = [item.toLocalFile() for item in event.mimeData().urls()] self.open_files_fromUrlList(event.mimeData().urls()) # print("\n\n dropEvent", paths) # self.open_file(file_path) def setFocus(self): widget = self.get_current_widget() if widget: widget.setFocus() def current_editor_changed(self, filename): """Notify the new filename of the current editor.""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.currentEditorChanged.emit(filename) def show_split(self, orientation_vertical=False): #IDE.select_current(self.current_widget.currentWidget()) self.current_widget.split_editor(orientation_vertical) def add_editor(self, fileName=None, ignore_checkers=False): print("filename::", fileName) ninjaide = IDE.getInstance() editable = ninjaide.get_or_create_editable(fileName) if editable.editor: self.current_widget.set_current(editable) print("\n\nreturn") return self.current_widget.currentWidget() else: editable.ignore_checkers = ignore_checkers editorWidget = self.create_editor_from_editable(editable) #add the tab keep_index = (self.splitter.count() > 1 and self.combo_area.stacked.count() > 0) self.combo_area.add_editor(editable, keep_index) #emit a signal about the file open self.fileOpened.emit(fileName) if keep_index: self.current_widget.set_current(editable) self.stack.setCurrentWidget(self.splitter) return editorWidget def create_editor_from_editable(self, editable): editorWidget = editor.create_editor(editable) #Connect signals editable.fileSaved.connect(self._editor_tab_was_saved) editorWidget.openDropFile.connect(self.open_file) editorWidget.addBackItemNavigation.connect(self.add_back_item_navigation) editorWidget.locateFunction.connect(self._editor_locate_function) editorWidget.findOcurrences.connect(self._find_occurrences) #keyPressEventSignal for plugins editorWidget.keyPressSignal.connect(self._editor_keyPressEvent) return editorWidget def reset_pep8_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.pep8.check_style() #else: #widget.hide_pep8_errors() def reset_lint_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() def _find_occurrences(self, word): self.findOcurrences.emit(word) def _editor_keyPressEvent(self, event): self.editorKeyPressEvent.emit(event) def _editor_locate_function(self, function, filePath, isVariable): self.locateFunction.emit(function, filePath, isVariable) def _editor_tab_was_saved(self, editable=None): self.updateLocator.emit(editable.file_path) def get_current_widget(self): return self.current_widget.currentWidget() def get_current_editor(self): """Return the Actual Editor or None Return an instance of Editor if the Current Tab contains an Editor or None if it is not an instance of Editor""" widget = self.current_widget.currentWidget() if isinstance(widget, editor.Editor): return widget return None def reload_file(self, editorWidget=None): if editorWidget is None: editorWidget = self.get_current_editor() if editorWidget is not None: editorWidget.neditable.reload_file() def add_tab(self, widget, tabName, tabIndex=None): pass #return self.tabs.add_tab(widget, tabName, index=tabIndex) def open_image(self, fileName): try: if not self.is_open(fileName): viewer = image_viewer.ImageViewer(fileName) self.add_tab(viewer, file_manager.get_basename(fileName)) viewer.ID = fileName else: self.move_to_open(fileName) except Exception as reason: logger.error('open_image: %s', reason) QMessageBox.information(self, self.tr("Incorrect File"), self.tr("The image couldn\'t be open")) def open_files_fromList(self, lst): for f in lst: self.open_file(f) def open_files_fromUrlList(self, lst): for f in lst: self.open_file(f.toLocalFile()) def open_file(self, filename='', line=-1, col=0, ignore_checkers=False): logger.debug("will try to open %s" % filename) if not filename: logger.debug("has nofilename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editorWidget = self.get_current_editor() ninjaide = IDE.getInstance() if ninjaide: current_project = ninjaide.get_current_project() if current_project is not None: directory = current_project elif editorWidget is not None and editorWidget.file_path: directory = file_manager.get_folder( editorWidget.file_path) extensions = ';;'.join( ['{}(*{})'.format(e.upper()[1:], e) for e in settings.SUPPORTED_EXTENSIONS + ['.*', '']]) fileNames = QFileDialog.getOpenFileNames(self, self.tr("Open File"), directory, extensions)[0]#list() else: logger.debug("has filename") fileNames = [filename] if not fileNames: return print("\n\nopen_file") othersFileNames = [] image_extensions = ('bmp', 'gif', 'jpeg', 'jpg', 'png') for filename in fileNames: print("nombre", filename) if QFileInfo(filename).isDir(): othersFileNames.extend( QFileDialog.getOpenFileNames(None, "Select files", filename, "Files (*.*)")[0] ) elif file_manager.get_file_extension(filename) in image_extensions: logger.debug("will open as image") self.open_image(filename) elif file_manager.get_file_extension(filename).endswith('ui'): logger.debug("will load in ui editor") self.w = uic.loadUi(filename) self.w.show() else: logger.debug("will try to open: " + filename) self.__open_file(filename, line, col, ignore_checkers) for filename in othersFileNames: print("nombre", filename) if QFileInfo(filename).isDir(): continue elif file_manager.get_file_extension(filename) in image_extensions: logger.debug("will open as image") self.open_image(filename) elif file_manager.get_file_extension(filename).endswith('ui'): logger.debug("will load in ui editor") self.w = uic.loadUi(filename) self.w.show() else: logger.debug("will try to open: " + filename) self.__open_file(filename, line, col, ignore_checkers) def __open_file(self, fileName='', line=-1, col=0, ignore_checkers=False): print("unio", fileName) try: editorWidget = self.add_editor(fileName, ignore_checkers=ignore_checkers) if line != -1: editorWidget.set_cursor_position(line, col) self.currentEditorChanged.emit(fileName) except file_manager.NinjaIOException as reason: QMessageBox.information(self, self.tr("The file couldn't be open"), str(reason)) def is_open(self, filename): pass #return self.tabs.is_open(filename) != -1 def move_to_open(self, filename): pass #FIXME: add in the current split? #if self.tabs.is_open(filename) != -1: #self.tabs.move_to_open(filename) #self.tabs.currentWidget().setFocus() #self.emit(SIGNAL("currentEditorChanged(QString)"), filename) def get_widget_for_id(self, filename): pass #widget = None #index = self.tabs.is_open(filename) #if index != -1: #widget = self.tabs.widget(index) #return widget def change_open_tab_id(self, idname, newId): """Search for the Tab with idname, and set the newId to that Tab.""" pass #index = self.tabs.is_open(idname) #if index != -1: #widget = self.tabs.widget(index) #tabName = file_manager.get_basename(newId) #self.tabs.change_open_tab_name(index, tabName) #widget.ID = newId def close_deleted_file(self, idname): """Search for the Tab with id, and ask the user if should be closed.""" pass #index = self.tabs.is_open(idname) #if index != -1: #result = QMessageBox.question(self, self.tr("Close Deleted File"), #self.tr("Are you sure you want to close the deleted file?\n" #"The content will be completely deleted."), #buttons=QMessageBox.Yes | QMessageBox.No) #if result == QMessageBox.Yes: #self.tabs.removeTab(index) def save_file(self, editorWidget=None): #FIXME: check how we handle this if not editorWidget: editorWidget = self.get_current_editor() if not editorWidget: return False try: #editorWidget.just_saved = True if (editorWidget.nfile.is_new_file or not editorWidget.nfile.has_write_permission()): return self.save_file_as() self.beforeFileSaved.emit(editorWidget.file_path) if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) editorWidget.neditable.save_content() #file_manager.store_file_content( #fileName, content, addExtension=False) encoding = file_manager.get_file_encoding(editorWidget.text()) editorWidget.encoding = encoding self.fileSaved.emit((self.tr("File Saved: %s") % editorWidget.file_path)) return True except Exception as reason: logger.error('save_file: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def save_file_as(self): editorWidget = self.get_current_editor() if not editorWidget: return False try: filters = '(*.py);;(*.*)' if editorWidget.file_path: ext = file_manager.get_file_extension(editorWidget.file_path) if ext != 'py': filters = '(*.%s);;(*.py);;(*.*)' % ext save_folder = self._get_save_folder(editorWidget.file_path) fileName = QFileDialog.getSaveFileName( self._parent, self.tr("Save File"), save_folder, filters) if not fileName: return False if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) editorWidget.neditable.save_content(path=fileName) editorWidget.register_syntax( file_manager.get_file_extension(fileName)) self.fileSaved.emit((self.tr("File Saved: %s") % fileName)) self.currentEditorChanged.emit(fileName) return True except file_manager.NinjaFileExistsException as ex: QMessageBox.information(self, self.tr("File Already Exists"), (self.tr("Invalid Path: the file '%s' " " already exists.") % ex.filename)) except Exception as reason: logger.error('save_file_as: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def _get_save_folder(self, fileName): """ Returns the root directory of the 'Main Project' or the home folder """ ninjaide = IDE.getInstance() current_project = ninjaide.get_current_project() if current_project: return current_project.path return os.path.expanduser("~") def save_project(self, projectFolder): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def save_all(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor: #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #self.tabsecondary.check_for_external_modifications(editorWidget) #if type(editorWidget) is editor.Editor: #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def call_editors_function(self, call_function, *arguments): pass #args = arguments[0] #kwargs = arguments[1] #for i in range(self.tabs.count()): #editorWidget = self.tabs.widget(i) #if isinstance(editorWidget, editor.Editor): #function = getattr(editorWidget, call_function) #function(*args, **kwargs) #TODO: add other splits def show_start_page(self): start = self.stack.widget(0) if isinstance(start, start_page.StartPage): self.stack.setCurrentIndex(0) else: startPage = start_page.StartPage(parent=self) startPage.openProject.connect(self.open_project) startPage.openPreferences.connect(self.openPreferences.emit) startPage.newFile.connect(self.add_editor) startPage.openFiles.connect(self.open_files_fromList) self.stack.insertWidget(0, startPage) self.stack.setCurrentIndex(0) self.tryMakeImagePreview(0) #"screen0.png" def show_python_doc(self): if sys.platform == 'win32': self.docPage = browser_widget.BrowserWidget( 'http://docs.python.org/') else: process = runner.start_pydoc() self.docPage = browser_widget.BrowserWidget(process[1], process[0]) self.add_tab(self.docPage, translations.TR_PYTHON_DOC) def show_report_bugs(self): webbrowser.open(resources.BUGS_PAGE) def show_plugins_doc(self): bugsPage = browser_widget.BrowserWidget(resources.PLUGINS_DOC, self) self.add_tab(bugsPage, translations.TR_HOW_TO_WRITE_PLUGINS) def editor_jump_to_line(self, lineno=None): """Jump to line *lineno* if it is not None otherwise ask to the user the line number to jump """ editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(lineno=lineno) def get_opened_documents(self): #return self.tabs.get_documents_data() return [] def check_for_unsaved_files(self): pass #return self.tabs._check_unsaved_tabs() def get_unsaved_files(self): pass #return self.tabs.get_unsaved_files() def reset_editor_flags(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.set_flags() def _specify_syntax(self, widget, syntaxLang): if isinstance(widget, editor.Editor): widget.restyle(syntaxLang) def apply_editor_theme(self, family, size): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.restyle() #widget.set_font(family, size) def update_editor_margin_line(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget._update_margin_line() def open_project(self, path): print("open_project") self.openProject.emit(path) def close_python_doc(self): pass #close the python document server (if running) #if self.docPage: #index = self.tabs.indexOf(self.docPage) #self.tabs.removeTab(index) ##assign None to the browser #self.docPage = None def close_file(self): """Close the current tab in the current TabWidget.""" self.current_widget.close_current_file() def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def change_tab(self): """Change the tab in the current TabWidget.""" print("\nchange_tab") self.stack.setCurrentWidget(self.splitter) # self._files_handler.next_item() pass def change_tab_reverse(self): """Change the tab in the current TabWidget backwards.""" print("\nchange_tab_reverse") self.stack.setCurrentWidget(self.splitter) # self._files_handler.previous_item() def toggle_tabs_and_spaces(self): """ Toggle Show/Hide Tabs and Spaces """ settings.SHOW_TABS_AND_SPACES = not settings.SHOW_TABS_AND_SPACES qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) def show_navigation_buttons(self): """Show Navigation menu.""" self.stack.setCurrentWidget(self.splitter) self.combo_area.show_menu_navigation() def change_split_focus(self): pass #FIXME: check how we handle this #if self.actualTab == self._tabMain and self.tabsecondary.isVisible(): #self.actualTab = self.tabsecondary #else: #self.actualTab = self._tabMain #widget = self.actualTab.currentWidget() #if widget is not None: #widget.setFocus() def shortcut_index(self, index): pass #self.tabs.setCurrentIndex(index) def print_file(self): """Call the print of ui_tool Call print of ui_tool depending on the focus of the application""" #TODO: Add funtionality for proyect tab and methods tab editorWidget = self.get_current_editor() if editorWidget is not None: fileName = "newDocument.pdf" if editorWidget.file_path: fileName = file_manager.get_basename( editorWidget.file_path) fileName = fileName[:fileName.rfind('.')] + '.pdf' ui_tools.print_file(fileName, editorWidget.print_) def split_assistance(self): dialog = split_orientation.SplitOrientation(self) dialog.show() def close_split(self): if self.current_widget != self.combo_area: self.current_widget.bar.close_split() def split_vertically(self): self.show_split(False) def split_horizontally(self): self.show_split(True) def navigate_back(self): self.__navigate_with_keyboard(False) def navigate_forward(self): self.__navigate_with_keyboard(True)
class double_thresold(QWidget): from_slider_min = pyqtSignal(str) from_slider_max = pyqtSignal(str) from_line_min = pyqtSignal(int) from_line_max = pyqtSignal(int) from_label_min = pyqtSignal(int) from_label_max = pyqtSignal(int) def __init__(self, img_path='1023.png'): super().__init__() self.minValue = 100 self.maxValue = 200 self.press = 0 self.now = 0 self.img_path = img_path self.init_ui() # self.histpath(self.img_path) # 初始化 def init_ui(self): # 设置窗口大小,标题 self.setFixedSize(750, 300) self.setWindowModality(Qt.ApplicationModal) self.move(300, 300) self.setWindowTitle("Double Threshold") # 定义框架,主框架下有左右两个盒式框架,左侧框架中是堆叠框架,实现控件的堆叠,右侧框架(纵向排列)中有两个横向排列盒式框架,存放标签、文本框和滑块 self.main_box = QHBoxLayout() self.left1 = QVBoxLayout() self.stack = QStackedLayout() self.right1 = QVBoxLayout() self.right1_1 = QHBoxLayout() self.right1_2 = QHBoxLayout() # 定义控件,F为嵌入的matplotlib图像 try: self.F = MyFigure() # self.F.hist(self.img_path) self.F.setMinimumWidth(500) self.F.setMaximumWidth(500) self.right1.setSpacing(10) self.right1_1.setSpacing(10) self.right1_2.setSpacing(10) self.label1_1 = QLabel("Min Val:") self.lineEdit1_1 = QLineEdit("100") self.lineEdit1_1.setMaximumWidth(70) self.slider1_1 = QSlider(Qt.Horizontal) self.slider1_1.setFocusPolicy(Qt.NoFocus) self.slider1_1.setRange(0, 255) self.slider1_1.setValue(100) self.label1_2 = QLabel("Max Val:") self.lineEdit1_2 = QLineEdit("200") self.lineEdit1_2.setMaximumWidth(70) self.slider1_2 = QSlider(Qt.Horizontal) self.slider1_2.setFocusPolicy(Qt.NoFocus) self.slider1_2.setRange(0, 255) self.slider1_2.setValue(200) self.button1_3 = QPushButton("Apply to Image") # 用label和F的堆叠实现用蓝色色块标注当前选中区域的功能 self.mask = QLabel() # 堆叠框架只能间接添加框架 self.mask_layout_widget = QWidget() self.mask_layout = QHBoxLayout() self.mask_layout.addWidget(self.mask) self.mask_layout_widget.setLayout(self.mask_layout) # 绑定控件的事件 self.slider1_1.valueChanged.connect(self.change_sld_min_value) self.slider1_2.valueChanged.connect(self.change_sld_max_value) self.lineEdit1_1.editingFinished.connect( self.change_line_min_value_finished) self.lineEdit1_2.editingFinished.connect( self.change_line_max_value_finished) self.mask.mousePressEvent = self.label_mouse_press_event self.mask.mouseMoveEvent = self.label_mouse_move_event except Exception as err: print("set widgets:{0}".format(err)) # 把控件添加到框架中 try: self.left1.addLayout(self.stack) self.stack.addWidget(self.F) self.stack.addWidget(self.mask_layout_widget) self.right1_1.addWidget(self.label1_1) self.right1_1.addWidget(self.lineEdit1_1) self.right1_1.addWidget(self.slider1_1) self.right1_2.addWidget(self.label1_2) self.right1_2.addWidget(self.lineEdit1_2) self.right1_2.addWidget(self.slider1_2) self.right1.addLayout(self.right1_1) self.right1.addLayout(self.right1_2) self.right1.addWidget(self.button1_3) except Exception as err: print(err) # 对框架进行设置,并把框架添加到主框架中 try: self.stack.setStackingMode(1) self.main_box.addLayout(self.left1) self.main_box.addLayout(self.right1) self.setLayout(self.main_box) except Exception as err: print(err) # 设置色块label覆盖区域的初始数据,如边距和颜色 try: self.mask_left_margin = 78 self.mask_up_margin = 33 self.mask_right_margin = 65 self.mask_bottom_margin = 30 self.mask_range = self.F.width( ) - self.mask_left_margin - self.mask_right_margin self.mask.setStyleSheet( "QLabel{background-color: rgb(0,0,255,50);}") self.mask_layout.setContentsMargins(self.eva_start(), self.mask_up_margin, self.eva_end(), self.mask_bottom_margin) except Exception as err: print("mask Error:{0}".format(err)) # 为设置的信号绑定函数 try: self.from_slider_min.connect(self.change_line_min_value) self.from_slider_min.connect(self.change_label_min) self.from_slider_max.connect(self.change_line_max_value) self.from_slider_max.connect(self.change_label_max) self.from_line_min.connect(self.change_sld_min_value) self.from_line_min.connect(self.change_label_min) self.from_line_max.connect(self.change_sld_max_value) self.from_line_max.connect(self.change_label_max) self.from_label_max.connect(self.change_line_max_value) self.from_label_max.connect(self.change_sld_max_value) self.from_label_min.connect(self.change_line_min_value) self.from_label_min.connect(self.change_sld_min_value) except Exception as err: print("Signal Error:{0}".format(err)) def histpath(self, path): self.img_path = path self.F.hist(self.img_path) # 分解拖动 = 按下 + 移动 # 按下事件,记录按下时的位置 def label_mouse_press_event(self, event): if event.buttons() == Qt.LeftButton: self.press = event.pos().x() # 移动事件,仅在左键被按下时进行处理,获取当前的位置,计算和初始位置的差值,把差值传递到移动label的函数 def label_mouse_move_event(self, event): if event.buttons() == Qt.LeftButton: self.now = event.pos().x() self.differ = self.now - self.press self.move_mask(self.differ) # 判定文本是否符合要求 def is_available_int(self, text): try: if int(text) >= 0 and int(text) <= 255: return True return False except: print("except") return False # 计算label色块的左边界 def eva_start(self): return int(round( self.minValue * self.mask_range / 255.0)) + self.mask_left_margin # 计算label色块的右边界 def eva_end(self): return int(round((255 - self.maxValue) * self.mask_range / 255.0)) + self.mask_right_margin # 拖动滑块触发的事件,区分是操作控件时触发还是其他控件的信号触发 def change_sld_min_value(self, value): # 其他信号触发 if type(self.sender()) != QSlider: # 屏蔽自身信号,避免死循环 self.slider1_1.blockSignals(True) try: self.slider1_1.setValue(value) except Exception as err: print("err in set slider1_1 value: {0}".format(err)) self.slider1_1.blockSignals(False) # 自身信号触发 else: if value > self.maxValue: QMessageBox.information( self, "Warning", "Minimum value cannot be greater than maximum value") value = 0 self.slider1_1.setValue(value) else: self.from_slider_min.emit(str(value)) # 拖动滑块触发的事件,区分是操作控件时触发还是其他控件的信号触发 def change_sld_max_value(self, value): # 其他信号触发 if type(self.sender()) != QSlider: # 屏蔽自身信号,避免死循环 self.slider1_2.blockSignals(True) try: self.slider1_2.setValue(value) except Exception as err: print("err in set slider1_2 value: {0}".format(err)) self.slider1_2.blockSignals(False) # 自身信号触发 else: if value < self.minValue: QMessageBox.information( self, "Warning", "Maximum value cannot be less than minimum value") value = 255 self.slider1_2.setValue(value) else: self.from_slider_max.emit(str(value)) # 更改文本(Min Val)触发的事件,区分是操作控件时触发还是其他控件的信号触发 def change_line_min_value(self, text): # 来自其他信号 if type(self.sender()) != QLineEdit: self.lineEdit1_1.blockSignals(True) self.lineEdit1_1.setText(str(text)) self.lineEdit1_1.blockSignals(False) else: # 来自自身事件信号 # 判定文本是否符合要求 if self.is_available_int(text): if int(text) > self.maxValue: QMessageBox.information( self, "Warning", "Minimum value cannot be greater than maximum value") text = "0" self.lineEdit1_1.setText(str(text)) else: self.from_line_min.emit(int(text)) else: QMessageBox.information( self, "Attention", "Please enter a positive integer between 0 and 255") self.lineEdit1_1.blockSignals(True) self.lineEdit1_1.setText("0") self.lineEdit1_1.blockSignals(False) def change_line_min_value_finished(self): text = self.lineEdit1_1.text() # 来自其他信号 if type(self.sender()) != QLineEdit: self.lineEdit1_1.blockSignals(True) self.lineEdit1_1.setText(str(text)) self.lineEdit1_1.blockSignals(False) else: # 来自自身事件信号 # 判定文本是否符合要求 if self.is_available_int(text): if int(text) > self.maxValue: QMessageBox.information( self, "Warning", "Minimum value cannot be greater than maximum value") text = "0" self.lineEdit1_1.setText(str(text)) else: self.from_line_min.emit(int(text)) else: QMessageBox.information( self, "Attention", "Please enter a positive integer between 0 and 255") self.lineEdit1_1.blockSignals(True) self.lineEdit1_1.setText("0") self.lineEdit1_1.blockSignals(False) def change_line_max_value(self, text): if type(self.sender()) != QLineEdit: # 其他信号触发 self.lineEdit1_2.blockSignals(True) self.lineEdit1_2.setText(str(text)) self.lineEdit1_2.blockSignals(False) else: # 来自自身事件信号 # 判定文本是否符合要求 if self.is_available_int(text): if int(text) < self.minValue: QMessageBox.information( self, "Warning", "Maximum value cannot be less than minimum value") text = "255" self.lineEdit1_2.setText(str(text)) else: self.from_line_max.emit(int(text)) else: QMessageBox.information( self, "Attention", "Please enter a positive integer between 0 and 255") self.lineEdit1_2.blockSignals(True) self.lineEdit1_2.setText("255") self.lineEdit1_2.blockSignals(False) def change_line_max_value_finished(self): text = self.lineEdit1_2.text() if type(self.sender()) != QLineEdit: # 其他信号触发 self.lineEdit1_2.blockSignals(True) self.lineEdit1_2.setText(str(text)) self.lineEdit1_2.blockSignals(False) else: # 来自自身事件信号 # 判定文本是否符合要求 if self.is_available_int(text): if int(text) < self.minValue: QMessageBox.information( self, "Warning", "Maximum value cannot be less than minimum value") text = "255" self.lineEdit1_2.setText(str(text)) else: self.from_line_max.emit(int(text)) else: QMessageBox.information( self, "Attention", "Please enter a positive integer between 0 and 255") self.lineEdit1_2.blockSignals(True) self.lineEdit1_2.setText("255") self.lineEdit1_2.blockSignals(False) # 只会从其他控件处收到信号,更改色块显示的范围 def change_label_min(self, left): if self.is_available_int(left): if int(left) <= self.maxValue: self.minValue = int(left) self.mask_layout.setContentsMargins(self.eva_start(), self.mask_up_margin, self.eva_end(), self.mask_bottom_margin) # 只会从其他控件处收到信号,更改色块显示的范围 def change_label_max(self, right): if self.is_available_int(right): if int(right) >= self.minValue: self.maxValue = int(right) self.mask_layout.setContentsMargins(self.eva_start(), self.mask_up_margin, self.eva_end(), self.mask_bottom_margin) # 拖动色块时触发,重新计算左右边界,并把信号传递到其他控件 def move_mask(self, diff): if self.is_available_int( self.minValue + diff) and self.is_available_int(self.maxValue + diff): self.minValue += diff self.maxValue += diff self.avail_range = self.maxValue - self.minValue self.mask_layout.setContentsMargins(self.eva_start(), self.mask_up_margin, self.eva_end(), self.mask_bottom_margin) self.from_label_min.emit(self.minValue) self.from_label_max.emit(self.maxValue) elif self.is_available_int(self.minValue + diff): self.maxValue = 255 self.minValue = 255 - self.avail_range self.mask_layout.setContentsMargins(self.eva_start(), self.mask_up_margin, self.eva_end(), self.mask_bottom_margin) self.from_label_min.emit(self.minValue) self.from_label_max.emit(self.maxValue) elif self.minValue + diff < 0: self.minValue = 0 self.maxValue = self.avail_range self.mask_layout.setContentsMargins(self.eva_start(), self.mask_up_margin, self.eva_end(), self.mask_bottom_margin) self.from_label_min.emit(self.minValue) self.from_label_max.emit(self.maxValue) # 按下按钮时触发,对图片进行处理,先处理大于Min的部分,然后处理小于Max的部分,然后取交集 def apply(self): try: if is_gray(self.img_path): self.img = skimage.io.imread(self.img_path) # ret, temp_image1 = cv2.threshold(self.img, self.minValue, 255, cv2.THRESH_BINARY) # ret, temp_image2 = cv2.threshold(self.img, self.maxValue, 255, cv2.THRESH_BINARY_INV) # image = cv2.bitwise_and(temp_image1, temp_image2) dt = np.zeros_like(self.img) dt[(self.img >= self.minValue) & (self.img <= self.maxValue)] = 1.0 # cv2.imshow("double threshold", dt * 255) # cv2.waitKey() # cv2.destroyAllWindows() dt *= 255 return dt except Exception as err: print("apply error:{}".format(err))
class DualScale(QWidget): def __init__(self, parent=None, in_designer=False): QWidget.__init__(self, parent=parent) self.in_designer = in_designer self.d_vertically_flipped = False ui = self.getPath() # TODO: CAMPid 9549757292917394095482739548437597676742 if not QFileInfo(ui).isAbsolute(): ui_file = os.path.join(QFileInfo.absolutePath(QFileInfo(__file__)), ui) else: ui_file = ui ui_file = QFile(ui_file) ui_file.open(QFile.ReadOnly | QFile.Text) ts = QTextStream(ui_file) sio = io.StringIO(ts.readAll()) self.ui = uic.loadUi(sio, self) self.scale1 = epyqlib.widgets.scale.Scale(self, in_designer) self.scale2 = epyqlib.widgets.scale.Scale(self, in_designer) # color ranges, scale markers, labels, needle painted. self.scale1.scale.m_paintMode = 1 # needle, cover painted. self.scale2.scale.m_paintMode = 3 # scale2's needle is blue self.scale2.scale.isBlue = True self.stackedLayout = QStackedLayout() self.stackedLayout.addWidget(self.scale2) self.stackedLayout.addWidget(self.scale1) self.stackedLayout.setStackingMode(1) self.ui.glayout.addLayout(self.stackedLayout, 0, 0) # Trying to figure out how to get lower min and the higher max and change the scale # true_min = min(self.scale1.ui.scale.m_minimum, self.scale2.ui.scale.m_minimum) # true_max = max(self.scale1.ui.scale.m_maximum, self.scale2.ui.scale.m_maximum) # self.scale1.minimum = true_min # self.scale2.minimum = true_min # self.scale1.maximum = true_max # self.scale2.maximum = true_max # self.scale1.override_range = True # self.scale2.override_range = True def getPath(self): return os.path.join(QFileInfo.absolutePath(QFileInfo(__file__)), 'dualscale.ui') @pyqtProperty('QString') def scale1_signal_path(self): return self.scale1.signal_path @scale1_signal_path.setter def scale1_signal_path(self, value): self.scale1.signal_path = value @pyqtProperty(bool) def scale1_label_visible(self): return self.scale1.label_visible @scale1_label_visible.setter def scale1_label_visible(self, new_visible): self.scale1.label_visible = new_visible @pyqtProperty('QString') def scale2_signal_path(self): return self.scale2.signal_path @scale2_signal_path.setter def scale2_signal_path(self, value): self.scale2.signal_path = value @pyqtProperty(bool) def scale2_label_visible(self): return self.scale2.label_visible @scale2_label_visible.setter def scale2_label_visible(self, new_visible): self.scale2.label_visible = new_visible @pyqtProperty(bool) def d_flipped(self): return self.d_vertically_flipped @d_flipped.setter def d_flipped(self, value): self.d_vertically_flipped = value self.scale1.s_flipped = value self.scale2.s_flipped = value @pyqtProperty(float) def lower_red_breakpoint(self): return self.scale1._breakpoints[0] @lower_red_breakpoint.setter def lower_red_breakpoint(self, breakpoint): self.scale1._breakpoints[0] = breakpoint self.scale1.update_configuration() @pyqtProperty(float) def lower_yellow_breakpoint(self): return self.scale1._breakpoints[1] @lower_yellow_breakpoint.setter def lower_yellow_breakpoint(self, breakpoint): self.scale1._breakpoints[1] = breakpoint self.scale1.update_configuration() @pyqtProperty(float) def upper_yellow_breakpoint(self): return self.scale1._breakpoints[2] @upper_yellow_breakpoint.setter def upper_yellow_breakpoint(self, breakpoint): self.scale1._breakpoints[2] = breakpoint self.scale1.update_configuration() @pyqtProperty(float) def upper_red_breakpoint(self): return self.scale1._breakpoints[3] @upper_red_breakpoint.setter def upper_red_breakpoint(self, breakpoint): self.scale1._breakpoints[3] = breakpoint self.scale1.update_configuration() @pyqtProperty(QColor) def lower_red_color(self): return self.scale1._colors[0] @lower_red_color.setter def lower_red_color(self, color): self.scale1._colors[0] = color self.scale1.update_configuration() @pyqtProperty(QColor) def lower_yellow_color(self): return self.scale1._colors[1] @lower_yellow_color.setter def lower_yellow_color(self, color): self.scale1._colors[1] = color self.scale1.update_configuration() @pyqtProperty(QColor) def green_color(self): return self.scale1._colors[2] @green_color.setter def green_color(self, color): self.scale1._colors[2] = color self.scale1.update_configuration() @pyqtProperty(QColor) def upper_yellow_color(self): return self.scale1._colors[3] @upper_yellow_color.setter def upper_yellow_color(self, color): self.scale1._colors[3] = color self.scale1.update_configuration() @pyqtProperty(QColor) def upper_red_color(self): return self.scale1._colors[4] @upper_red_color.setter def upper_red_color(self, color): self.scale1._colors[4] = color self.scale1.update_configuration()
class GrandCalculatorUnitWidget(UnitWidget, UniversalUniqueIdentifiable): def __init__(self, unit_view, parent=None, size=32, *args, **kwargs): super().__init__(unit_view, parent, size, *args, **kwargs) del self.unitName self.card_widget = QWidget(self) self.unit_view = unit_view self.cards_internal = [None] * 15 self.cards = list() for idx in range(15): if idx % 5 == 0: color = 'red' else: color = 'black' card = UnitCard(unit_widget=self, card_idx=idx, size=size, color=color) self.cards.append(card) self.size = size self.path = IMAGE_PATH32 self.verticalLayout = QVBoxLayout() self.cardLayouts = [QHBoxLayout(), QHBoxLayout(), QHBoxLayout()] for idx, card in enumerate(self.cards): card.setMinimumSize(QSize(self.size + 2, self.size + 2)) self.cardLayouts[idx // 5].addWidget(card) for card_layout in self.cardLayouts: self.verticalLayout.addLayout(card_layout) self.card_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.card_widget.setLayout(self.verticalLayout) # Setup overlay self.label = QLabel(self.card_widget) self.label.setText("Running...") font = QFont() font.setPixelSize(20) self.label.setFont(font) self.label.setAlignment(Qt.AlignCenter) self.label.setStyleSheet("background-color: rgba(255, 255, 255, 100);") self.label.setAutoFillBackground(True) self.stacked_layout = QStackedLayout() self.stacked_layout.addWidget(self.card_widget) self.stacked_layout.addWidget(self.label) self.stacked_layout.setContentsMargins(0, 0, 0, 0) self.stacked_layout.setStackingMode(QStackedLayout.StackAll) self.setLayout(self.stacked_layout) self.toggle_running_simulation(False) self.running_simulation = False def toggle_running_simulation(self, running=False): self.label.setVisible(running) self.running_simulation = running def permute_units(self): self.unit_view.permute_units() def handle_lost_mime(self, mime_text): pass
class _MainContainer(QWidget): currentEditorChanged = pyqtSignal("QString") fileOpened = pyqtSignal("QString") fileSaved = pyqtSignal("QString") def __init__(self, parent=None): super().__init__(parent) self.setAcceptDrops(True) self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self._files_handler = files_handler.FilesHandler(self) # Code Navigation self.__operations = { 0: self._navigate_bookmarks } # QML UI self._add_file_folder = add_file_folder.AddFileFolderWidget(self) if settings.SHOW_START_PAGE: self.show_start_page() IDE.register_service("main_container", self) # Register signals connections connections = ( { "target": "main_container", "signal_name": "updateLocator", "slot": self._explore_code }, { "target": "filesystem", "signal_name": "projectOpened", "slot": self._explore_code }, { "target": "projects_explore", "signal_name": "updateLocator", "slot": self._explore_code } ) IDE.register_signals("main_container", connections) esc_sort = QShortcut(QKeySequence(Qt.Key_Escape), self) esc_sort.activated.connect(self._set_focus_to_editor) # Added for set language self._setter_language = set_language.SetLanguageFile() def install(self): ninjaide = IDE.get_service("ide") ninjaide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.combo_area.allFilesClosed.connect(self._files_closed) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) # self.current_widget = self.combo_area # Code Locator self._code_locator = locator_widget.LocatorWidget(ninjaide) ui_tools.install_shortcuts(self, actions.ACTIONS, ninjaide) def show_files_handler(self): self._files_handler.next_item() def navigate_code_history(self, operation, forward): self.__operations[operation](forward) def _navigate_bookmarks(self, forward=True): current_editor = self.get_current_editor() current_editor.navigate_bookmarks(forward=forward) def _set_focus_to_editor(self): status_bar = IDE.get_service("status_bar") tools_doock = IDE.get_service("tools_dock") editor_widget = self.get_current_editor() if status_bar.isVisible() and tools_doock.isVisible(): status_bar.hide_status_bar() elif tools_doock.isVisible(): tools_doock._hide() elif status_bar.isVisible(): status_bar.hide_status_bar() if editor_widget is not None: editor_widget.clear_extra_selections('searchs') def split_assistance(self): split_widget = split_orientation.SplitOrientation(self) split_widget.show() def show_dialog(self, widget): self.add_widget(widget) self.stack.setCurrentWidget(widget) def show_split(self, orientation_vertical=False): orientation = Qt.Horizontal if orientation_vertical: orientation = Qt.Vertical self.combo_area.split_editor(orientation) def show_locator(self): """Show the Locator Widget""" if not self._code_locator.isVisible(): self._code_locator.show() def _explore_code(self): """Update locator metadata for the current projects""" self._code_locator.explore_code() def current_editor_changed(self, filename): """Notify the new filename of the current editor""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.currentEditorChanged.emit(filename) def get_current_editor(self): current_widget = self.combo_area.current_editor() if isinstance(current_widget, editor.NEditor): return current_widget return None def open_file(self, filename='', line=-1, col=0, ignore_checkers=False): logger.debug("Will try to open %s" % filename) if not filename: logger.debug("Has no filename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editor_widget = self.get_current_editor() ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() # TODO: handle current project in NProject if current_project is not None: directory = current_project.full_path elif editor_widget is not None and editor_widget.file_path: directory = file_manager.get_folder( editor_widget.file_path) filenames = QFileDialog.getOpenFileNames( self, "Open File", # FIXME: translations directory, settings.get_supported_extensions_filter() )[0] else: logger.debug("Has filename") filenames = [filename] if not filenames: return for filename in filenames: image_extensions = ("png", "jpg", "jpeg", "bmp", "gif") if file_manager.get_file_extension(filename) in image_extensions: logger.debug("Will open as image") self.open_image(filename) else: logger.debug("Will try to open: %s" % filename) self.__open_file( filename, line, col, ignore_checkers=ignore_checkers) def __open_file(self, filename, line, col, ignore_checkers=False): try: editor_widget = self.add_editor(filename) if line != -1: editor_widget.go_to_line(line, col) self.currentEditorChanged.emit(filename) except file_manager.NinjaIOException as reason: QMessageBox.information( self, "The file couldn't be open", # FIXME: translations str(reason)) logger.error("The file %s couldn't be open" % filename) def open_image(self, filename): for index in range(self.combo_area.stacked.count()): widget = self.combo_area.stacked.widget(index) if isinstance(widget, image_viewer.ImageViewer): if widget.image_filename == filename: logger.debug("Image already open") self.combo_area._set_current(neditable=None, index=index) return viewer = image_viewer.ImageViewer(filename) self.combo_area.add_image_viewer(viewer) self.stack.setCurrentWidget(self.splitter) def save_file(self, editor_widget=None): if editor_widget is None: # This may return None if there is not editor present editor_widget = self.get_current_editor() if editor_widget is None: return False # Ok, we have an editor instance # Save to file only if editor really was modified if editor_widget.is_modified: try: if editor_widget.nfile.is_new_file or \ not editor_widget.nfile.has_write_permission(): return self.save_file_as(editor_widget) # FIXME: beforeFileSaved.emit if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editor_widget) # FIXME: new line at end if settings.ADD_NEW_LINE_AT_EOF: helpers.insert_block_at_end(editor_widget) # Save content editor_widget.neditable.save_content() # FIXME: encoding # FIXME: translations self.fileSaved.emit("File Saved: %s" % editor_widget.file_path) return True except Exception as reason: logger.error("Save file error: %s" % reason) QMessageBox.information( self, "Save Error", "The file could't be saved!" ) return False def save_file_as(self, editor_widget=None): force = False if editor_widget is None: # We invoque from menu editor_widget = self.get_current_editor() if editor_widget is None: # We haven't editor in main container return False force = True try: filters = "(*.py);;(*.*)" if editor_widget.file_path is not None: # Existing file extension = file_manager.get_file_extension( editor_widget.file_path) if extension != 'py': filters = "(*.%s);;(*.py);;(*.*)" % extension save_folder = self._get_save_folder(editor_widget.file_path) filename = QFileDialog.getSaveFileName( self, "Save File", save_folder, filters )[0] if not filename: return False # FIXME: remove trailing spaces extension = file_manager.get_file_extension(filename) if not extension: filename = "%s.%s" % (filename, "py") editor_widget.neditable.save_content(path=filename, force=force) self._setter_language.set_language_from_extension(extension) self.fileSaved.emit("File Saved: {}".format(filename)) self.currentEditorChanged.emit(filename) return True except file_manager.NinjaFileExistsException as reason: QMessageBox.information( self, "File Already Exists", "Invalid Path: the file '%s' already exists." % reason.filename ) except Exception as reason: logger.error("save_file_as: %s", reason) QMessageBox.information( self, "Save Error", "The file couldn't be saved!" ) return False def save_project(self, project_path): """Save all files in the project path""" for neditable in self.combo_area.bar.get_editables(): file_path = neditable.file_path if file_manager.belongs_to_folder(project_path, file_path): neditable.save_content() def _get_save_folder(self, filename): """Returns the root directory of the 'Main Project' or the home folder""" ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() if current_project is not None: return current_project.path return os.path.expanduser("~") def close_file(self): self.combo_area.close_current_file() def add_editor(self, filename=None): ninjaide = IDE.get_service("ide") editable = ninjaide.get_or_create_editable(filename) if editable.editor: # If already open logger.debug("%s is already open" % filename) self.combo_area.set_current(editable) return self.combo_area.current_editor() else: pass editor_widget = self.create_editor_from_editable(editable) # editor_widget.set_language() # Add the tab keep_index = (self.splitter.count() > 1 and self.combo_area.stacked.count() > 0) self.combo_area.add_editor(editable, keep_index) # Emit a signal about the file open self.fileOpened.emit(filename) if not keep_index: self.combo_area.set_current(editable) self.stack.setCurrentWidget(self.splitter) editor_widget.setFocus() return editor_widget def create_editor_from_editable(self, editable): neditor = editor.create_editor(editable) neditor.zoomChanged.connect(self._show_zoom_indicator) neditor.destroyed.connect(self.__on_editor_destroyed) # editable.fileSaved.connect(self._editor_tab) return neditor def _show_zoom_indicator(self, zoom): neditor = self.get_current_editor() indicator.Indicator.show_text( neditor, "Zoom: {} %".format(str(zoom))) @pyqtSlot() def __on_editor_destroyed(self): indicator.Indicator.instance = None def add_widget(self, widget): self.stack.addWidget(widget) def show_start_page(self): """Show Start Page widget in main container""" startp = self.stack.widget(0) if isinstance(startp, start_page.StartPage): self.stack.setCurrentIndex(0) else: startp = start_page.StartPage(parent=self) startp.newFile.connect(self.add_editor) self.stack.insertWidget(0, startp) self.stack.setCurrentIndex(0) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def add_status_bar(self, status_bar): self._vbox.addWidget(status_bar) def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def zoom_in_editor(self): """Increase the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(1.) def zoom_out_editor(self): """Decrease the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(-1.) def reset_zoom_editor(self): """Reset the to original font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.reset_zoom() def editor_move_up(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down(up=True) def editor_move_down(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down() def editor_duplicate_line(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.duplicate_line() def editor_comment(self): """Mark the current line or selection as a comment.""" editor_widget = self.get_current_editor() if editor_widget is not None: helpers.comment_or_uncomment(editor_widget) def editor_go_to_line(self, line): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.go_to_line(line) editor_widget.setFocus() def _editor_settings_changed(self, key, value): key = key.split("/")[-1] editor_widget = self.get_current_editor() if editor_widget is not None: callback = getattr(editor.NEditor, key, False) if callback: callback = callback if not hasattr(callback, "__call__"): # Property! callback = callback.fset callback(editor_widget, value) def toggle_tabs_and_spaces(self): """Toggle Show/Hide Tabs and Spaces""" settings.SHOW_TABS_AND_SPACES = not settings.SHOW_TABS_AND_SPACES qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) neditor = self.get_current_editor() if neditor is not None: neditor.show_whitespaces = settings.SHOW_TABS_AND_SPACES
class _MainContainer(QWidget): currentEditorChanged = pyqtSignal(str) fileOpened = pyqtSignal(str) beforeFileSaved = pyqtSignal(str) fileSaved = pyqtSignal(str) runFile = pyqtSignal(str) showFileInExplorer = pyqtSignal(str) addToProject = pyqtSignal(str) allFilesClosed = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.setAcceptDrops(True) self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self._files_handler = files_handler.FilesHandler(self) # Code Navigation self.__code_back = [] self.__code_forward = [] self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks } # Recent files list self.__last_opened_files = [] # QML UI self._add_file_folder = add_file_folder.AddFileFolderWidget(self) if settings.SHOW_START_PAGE: self.show_start_page() IDE.register_service("main_container", self) # Register signals connections connections = ( # "slot": self._explore_code { "target": "filesystem", "signal_name": "projectOpened", "slot": self._explore_code }, # "slot": self._explore_code { "target": "filesystem", "signal_name": "projectClosed", "slot": self._explore_code }) IDE.register_signals("main_container", connections) fhandler_short = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Tab), self) fhandler_short.activated.connect(self.show_files_handler) # Added for set language def install(self): ninjaide = IDE.get_service("ide") ninjaide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.combo_area.allFilesClosed.connect(self._files_closed) self.combo_area.allFilesClosed.connect( lambda: self.allFilesClosed.emit()) self.combo_area.fileClosed.connect(self._add_to_last_opened) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) # Code Locator self._code_locator = locator_widget.LocatorWidget(ninjaide) data_settings = IDE.data_settings() recent_files = data_settings.value("lastSession/recentFiles") if recent_files is not None: self.__last_opened_files = recent_files ui_tools.install_shortcuts(self, actions.ACTIONS, ninjaide) def run_file(self, filepath): self.runFile.emit(filepath) def _show_file_in_explorer(self, filepath): self.showFileInExplorer.emit(filepath) def _add_to_project(self, filepath): self.addToProject.emit(filepath) def show_files_handler(self): self._files_handler.next_item() def hide_files_handler(self): self._files_handler.hide() def import_from_everywhere(self): """Insert an import line from any place in the editor.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def navigate_code_history(self, operation, forward): self.__operations[operation](forward) def _navigate_code_jumps(self, forward=False): """Navigate between the jump points""" node = None if not forward and self.__code_back: if len(self.__code_back) == 1: return node = self.__code_back.pop() self.__code_forward.append(node) node = self.__code_back[-1] elif forward and self.__code_forward: node = self.__code_forward.pop() self.__code_back.append(node) if node is not None: filename = node[0] line, col = node[1] self.open_file(filename, line, col) def _navigate_bookmarks(self, forward=True): """Navigate between the bookmarks""" current_editor = self.get_current_editor() current_editor.navigate_bookmarks(forward=forward) def _set_focus_to_editor(self): status_bar = IDE.get_service("status_bar") tools_doock = IDE.get_service("tools_dock") editor_widget = self.get_current_editor() if status_bar.isVisible() and tools_doock.isVisible(): status_bar.hide_status_bar() elif tools_doock.isVisible(): tools_doock._hide() elif status_bar.isVisible(): status_bar.hide_status_bar() if editor_widget is not None: editor_widget.extra_selections.remove("find") editor_widget.scrollbar().remove_marker("find") def split_assistance(self): editor_widget = self.get_current_editor() if editor_widget is not None: split_widget = split_orientation.SplitOrientation(self) split_widget.show() def show_dialog(self, widget): self.add_widget(widget) self.stack.setCurrentWidget(widget) def show_split(self, orientation_vertical=False): orientation = Qt.Horizontal if orientation_vertical: orientation = Qt.Vertical self.combo_area.split_editor(orientation) def show_locator(self): """Show the Locator Widget""" if not self._code_locator.isVisible(): self._code_locator.show() def _explore_code(self): """Update locator metadata for the current projects""" self._code_locator.explore_code() def _explore_file_code(self, path): """Update locator metadata for the file in path""" self._code_locator.explore_file_code(path) def current_editor_changed(self, filename): """Notify the new filename of the current editor""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.currentEditorChanged.emit(filename) def get_current_editor(self): current_widget = self.combo_area.current_editor() if isinstance(current_widget, editor.NEditor): return current_widget return None @property def last_opened_files(self): return self.__last_opened_files def _add_to_last_opened(self, nfile): MAX_RECENT_FILES = 10 # FIXME: configuration if nfile.is_new_file: return file_path = nfile.file_path if file_path in self.__last_opened_files: self.__last_opened_files.remove(file_path) self.__last_opened_files.insert(0, file_path) if len(self.__last_opened_files) > MAX_RECENT_FILES: self.__last_opened_files.pop(-1) def clear_last_opened_files(self): self.__last_opened_files.clear() def open_file(self, filename='', line=-1, col=0, ignore_checkers=False): if not filename: logger.debug("Has no filename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editor_widget = self.get_current_editor() ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() # TODO: handle current project in NProject if current_project is not None: directory = current_project.full_path elif editor_widget is not None and editor_widget.file_path: directory = file_manager.get_folder( editor_widget.file_path) filenames = QFileDialog.getOpenFileNames( self, translations.TR_OPEN_A_FILE, directory, settings.get_supported_extensions_filter(), initialFilter="Python files (*.py *.pyw)")[0] else: logger.debug("Has filename") filenames = [filename] if not filenames: return for filename in filenames: image_extensions = ("png", "jpg", "jpeg", "bmp", "gif") if file_manager.get_file_extension(filename) in image_extensions: logger.debug("Will open as image") self.open_image(filename) else: logger.debug("Will try to open: %s" % filename) self.__open_file(filename, line, col, ignore_checkers=ignore_checkers) def __open_file(self, filename, line, col, ignore_checkers=False): try: self.add_editor(filename) if line != -1: self.editor_go_to_line(line, col) self.currentEditorChanged.emit(filename) except file_manager.NinjaIOException as reason: QMessageBox.information(self, translations.TR_OPEN_FILE_ERROR, str(reason)) logger.error("The file %s couldn't be open" % filename) def open_image(self, filename): for index in range(self.combo_area.stacked.count()): widget = self.combo_area.stacked.widget(index) if isinstance(widget, image_viewer.ImageViewer): if widget.image_filename == filename: logger.debug("Image already open") self.combo_area._set_current(neditable=None, index=index) return viewer = image_viewer.ImageViewer(filename) self.combo_area.add_image_viewer(viewer) self.stack.setCurrentWidget(self.splitter) def autosave_file(self): for neditable in self.combo_area.bar.get_editables(): neditable.autosave_file() def save_file(self, editor_widget=None): if editor_widget is None: # This may return None if there is not editor present editor_widget = self.get_current_editor() if editor_widget is None: return False # Ok, we have an editor instance # Save to file only if editor really was modified if editor_widget.is_modified: try: if editor_widget.nfile.is_new_file or \ not editor_widget.nfile.has_write_permission(): return self.save_file_as(editor_widget) file_path = editor_widget.file_path # Emit signal before save self.beforeFileSaved.emit(file_path) if settings.REMOVE_TRAILING_SPACES: editor_widget.remove_trailing_spaces() if settings.ADD_NEW_LINE_AT_EOF: editor_widget.insert_block_at_end() # Save content editor_widget.neditable.save_content() # FIXME: encoding message = translations.TR_FILE_SAVED.format(file_path) self.fileSaved.emit(message) return True except Exception as reason: logger.error("Save file error: %s" % reason) QMessageBox.information(self, translations.TR_SAVE_FILE_ERROR_TITLE, translations.TR_SAVE_FILE_ERROR_BODY) return False def save_file_as(self, editor_widget=None): force = False if editor_widget is None: # We invoque from menu editor_widget = self.get_current_editor() if editor_widget is None: # We haven't editor in main container return False force = True try: filters = "(*.py);;(*.*)" if editor_widget.file_path is not None: # Existing file extension = file_manager.get_file_extension( editor_widget.file_path) if extension != 'py': filters = "(*.%s);;(*.py);;(*.*)" % extension save_folder = self._get_save_folder(editor_widget.file_path) else: save_folder = settings.WORKSPACE filename = QFileDialog.getSaveFileName( self, translations.TR_SAVE_FILE_DIALOG, save_folder, filters)[0] if not filename: return False # FIXME: remove trailing spaces extension = file_manager.get_file_extension(filename) if not extension: filename = "%s.%s" % (filename, "py") editor_widget.neditable.save_content(path=filename, force=force) self.fileSaved.emit(translations.TR_FILE_SAVED.format(filename)) self.currentEditorChanged.emit(filename) return True except file_manager.NinjaFileExistsException as reason: QMessageBox.information( self, translations.TR_FILE_ALREADY_EXISTS_TITLE, translations.TR_FILE_ALREADY_EXISTS_BODY.format( reason.filename)) except Exception as reason: logger.error("Save file as: %s", reason) QMessageBox.information(self, translations.TR_SAVE_FILE_ERROR_TITLE, translations.TR_SAVE_FILE_ERROR_BODY) return False def save_project(self, project_path): """Save all files in the project path""" for neditable in self.combo_area.bar.get_editables(): file_path = neditable.file_path if file_path is None: # FIXME: New edited files will not be saved, its ok? continue if file_manager.belongs_to_folder(project_path, file_path): neditable.save_content() def _get_save_folder(self, filename): """Returns the root directory of the 'Main Project' or the home folder""" ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() if current_project is not None: return current_project.path return os.path.expanduser("~") def close_file(self): self.combo_area.close_current_file() def add_editor(self, filename=None): ninjaide = IDE.get_service("ide") editable = ninjaide.get_or_create_editable(filename) if editable.editor: # If already open logger.debug("%s is already open" % filename) self.combo_area.set_current(editable) return self.combo_area.current_editor() else: pass editor_widget = self.create_editor_from_editable(editable) # Add the tab keep_index = (self.splitter.count() > 1 and self.combo_area.stacked.count() > 0) self.combo_area.add_editor(editable, keep_index) # Emit a signal about the file open self.fileOpened.emit(filename) if keep_index: self.combo_area.set_current(editable) self.stack.setCurrentWidget(self.splitter) editor_widget.setFocus() return editor_widget def create_editor_from_editable(self, editable): neditor = editor.create_editor(editable) neditor.zoomChanged.connect(self._on_zoom_changed) neditor.addBackItemNavigation.connect(self.add_back_item_navigation) editable.fileSaved.connect( lambda neditable: self._explore_file_code(neditable.file_path)) return neditor def add_back_item_navigation(self): editor_widget = self.get_current_editor() if editor_widget is not None: item = (editor_widget.file_path, editor_widget.cursor_position) if item not in self.__code_back: self.__code_back.append(item) def _on_zoom_changed(self, zoom): text = "Zoom: {}%".format(str(zoom)) ide = IDE.get_service("ide") ide.show_message(text) def add_widget(self, widget): self.stack.addWidget(widget) def show_start_page(self): """Show Start Page widget in main container""" startp = self.stack.widget(0) if isinstance(startp, start_page.StartPage): self.stack.setCurrentIndex(0) else: startp = start_page.StartPage(parent=self) startp.newFile.connect(self.add_editor) self.stack.insertWidget(0, startp) self.stack.setCurrentIndex(0) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def add_status_bar(self, status_bar): self._vbox.addWidget(status_bar) def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def restyle_editor(self): neditables = self.combo_area.bar.get_editables() for neditable in neditables: neditable.editor.restyle() def zoom_in_editor(self): """Increase the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(1.) def zoom_out_editor(self): """Decrease the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(-1.) def reset_zoom_editor(self): """Reset the to original font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.reset_zoom() def editor_move_up(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down(up=True) def editor_move_down(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down() def editor_duplicate_line(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.duplicate_line() def editor_toggle_comment(self): """Mark the current line or selection as a comment.""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.comment_or_uncomment() def editor_go_to_line(self, line, column=0, center=True): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.go_to_line(line, column, center) editor_widget.setFocus() def _editor_settings_changed(self, key, value): key = key.split("/")[-1] editor_widget = self.get_current_editor() if editor_widget is not None: callback = getattr(editor.NEditor, key, False) if callback: callback = callback if not hasattr(callback, "__call__"): # Property! callback = callback.fset callback(editor_widget, value) def toggle_tabs_and_spaces(self): """Toggle Show/Hide Tabs and Spaces""" settings.SHOW_TABS_AND_SPACES = not settings.SHOW_TABS_AND_SPACES qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) neditor = self.get_current_editor() if neditor is not None: neditor.show_whitespaces = settings.SHOW_TABS_AND_SPACES def __navigate_with_keyboard(self, forward): """Navigate between the positions in the jump history stack.""" operation = self.combo_area.bar.code_navigator.operation self.navigate_code_history(operation, forward) def navigate_back(self): self.__navigate_with_keyboard(forward=False) def navigate_forward(self): self.__navigate_with_keyboard(forward=True)
class _MainContainer(QWidget): currentEditorChanged = pyqtSignal(str) fileOpened = pyqtSignal(str) beforeFileSaved = pyqtSignal(str) fileSaved = pyqtSignal(str) runFile = pyqtSignal(str) showFileInExplorer = pyqtSignal(str) addToProject = pyqtSignal(str) allFilesClosed = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.setAcceptDrops(True) self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self._files_handler = files_handler.FilesHandler(self) # Code Navigation self.__code_back = [] self.__code_forward = [] self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks } # Recent files list self.__last_opened_files = [] # QML UI self._add_file_folder = add_file_folder.AddFileFolderWidget(self) if settings.SHOW_START_PAGE: self.show_start_page() IDE.register_service("main_container", self) # Register signals connections connections = ( # { # "target": "main_container", # "signal_name": "updateLocator", # "slot": self._explore_code # }, { "target": "filesystem", "signal_name": "projectOpened", "slot": self._explore_code }, # { # "target": "projects_explore", # "signal_name": "updateLocator", # "slot": self._explore_code # } { "target": "filesystem", "signal_name": "projectClosed", "slot": self._explore_code } ) IDE.register_signals("main_container", connections) fhandler_short = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Tab), self) fhandler_short.activated.connect(self.show_files_handler) # Added for set language # self._setter_language = set_language.SetLanguageFile() def install(self): ninjaide = IDE.get_service("ide") ninjaide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.combo_area.allFilesClosed.connect(self._files_closed) self.combo_area.allFilesClosed.connect( lambda: self.allFilesClosed.emit()) self.combo_area.fileClosed.connect(self._add_to_last_opened) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) # self.current_widget = self.combo_area # Code Locator self._code_locator = locator_widget.LocatorWidget(ninjaide) data_settings = IDE.data_settings() recent_files = data_settings.value("lastSession/recentFiles") if recent_files is not None: self.__last_opened_files = recent_files ui_tools.install_shortcuts(self, actions.ACTIONS, ninjaide) # self.fileSaved.connect(self._show_message_about_saved) def run_file(self, filepath): self.runFile.emit(filepath) def _show_file_in_explorer(self, filepath): self.showFileInExplorer.emit(filepath) def _add_to_project(self, filepath): self.addToProject.emit(filepath) def show_files_handler(self): self._files_handler.next_item() def hide_files_handler(self): self._files_handler.hide() def import_from_everywhere(self): """Insert an import line from any place in the editor.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def navigate_code_history(self, operation, forward): self.__operations[operation](forward) def _navigate_code_jumps(self, forward=False): """Navigate between the jump points""" node = None if not forward and self.__code_back: if len(self.__code_back) == 1: return node = self.__code_back.pop() self.__code_forward.append(node) node = self.__code_back[-1] elif forward and self.__code_forward: node = self.__code_forward.pop() self.__code_back.append(node) if node is not None: filename = node[0] line, col = node[1] self.open_file(filename, line, col) def _navigate_bookmarks(self, forward=True): """Navigate between the bookmarks""" current_editor = self.get_current_editor() current_editor.navigate_bookmarks(forward=forward) def _set_focus_to_editor(self): status_bar = IDE.get_service("status_bar") tools_doock = IDE.get_service("tools_dock") editor_widget = self.get_current_editor() if status_bar.isVisible() and tools_doock.isVisible(): status_bar.hide_status_bar() elif tools_doock.isVisible(): tools_doock._hide() elif status_bar.isVisible(): status_bar.hide_status_bar() if editor_widget is not None: editor_widget.extra_selections.remove("find") editor_widget.scrollbar().remove_marker("find") def split_assistance(self): editor_widget = self.get_current_editor() if editor_widget is not None: split_widget = split_orientation.SplitOrientation(self) split_widget.show() def show_dialog(self, widget): self.add_widget(widget) self.stack.setCurrentWidget(widget) def show_split(self, orientation_vertical=False): orientation = Qt.Horizontal if orientation_vertical: orientation = Qt.Vertical self.combo_area.split_editor(orientation) def show_locator(self): """Show the Locator Widget""" if not self._code_locator.isVisible(): self._code_locator.show() def _explore_code(self): """Update locator metadata for the current projects""" self._code_locator.explore_code() def _explore_file_code(self, path): """Update locator metadata for the file in path""" self._code_locator.explore_file_code(path) def current_editor_changed(self, filename): """Notify the new filename of the current editor""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.currentEditorChanged.emit(filename) def get_current_editor(self): current_widget = self.combo_area.current_editor() if isinstance(current_widget, editor.NEditor): return current_widget return None @property def last_opened_files(self): return self.__last_opened_files def _add_to_last_opened(self, nfile): MAX_RECENT_FILES = 10 # FIXME: configuration if nfile.is_new_file: return file_path = nfile.file_path if file_path in self.__last_opened_files: self.__last_opened_files.remove(file_path) self.__last_opened_files.insert(0, file_path) if len(self.__last_opened_files) > MAX_RECENT_FILES: self.__last_opened_files.pop(-1) def clear_last_opened_files(self): self.__last_opened_files.clear() def open_file(self, filename='', line=-1, col=0, ignore_checkers=False): if not filename: logger.debug("Has no filename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editor_widget = self.get_current_editor() ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() # TODO: handle current project in NProject if current_project is not None: directory = current_project.full_path elif editor_widget is not None and editor_widget.file_path: directory = file_manager.get_folder( editor_widget.file_path) filenames = QFileDialog.getOpenFileNames( self, translations.TR_OPEN_A_FILE, directory, settings.get_supported_extensions_filter(), initialFilter="Python files (*.py *.pyw)" )[0] else: logger.debug("Has filename") filenames = [filename] if not filenames: return for filename in filenames: image_extensions = ("png", "jpg", "jpeg", "bmp", "gif") if file_manager.get_file_extension(filename) in image_extensions: logger.debug("Will open as image") self.open_image(filename) else: logger.debug("Will try to open: %s" % filename) self.__open_file( filename, line, col, ignore_checkers=ignore_checkers) def __open_file(self, filename, line, col, ignore_checkers=False): try: self.add_editor(filename) if line != -1: self.editor_go_to_line(line, col) self.currentEditorChanged.emit(filename) except file_manager.NinjaIOException as reason: QMessageBox.information( self, translations.TR_OPEN_FILE_ERROR, str(reason)) logger.error("The file %s couldn't be open" % filename) def open_image(self, filename): for index in range(self.combo_area.stacked.count()): widget = self.combo_area.stacked.widget(index) if isinstance(widget, image_viewer.ImageViewer): if widget.image_filename == filename: logger.debug("Image already open") self.combo_area._set_current(neditable=None, index=index) return viewer = image_viewer.ImageViewer(filename) self.combo_area.add_image_viewer(viewer) self.stack.setCurrentWidget(self.splitter) def autosave_file(self): for neditable in self.combo_area.bar.get_editables(): neditable.autosave_file() def save_file(self, editor_widget=None): if editor_widget is None: # This may return None if there is not editor present editor_widget = self.get_current_editor() if editor_widget is None: return False # Ok, we have an editor instance # Save to file only if editor really was modified if editor_widget.is_modified: try: if editor_widget.nfile.is_new_file or \ not editor_widget.nfile.has_write_permission(): return self.save_file_as(editor_widget) file_path = editor_widget.file_path # Emit signal before save self.beforeFileSaved.emit(file_path) if settings.REMOVE_TRAILING_SPACES: editor_widget.remove_trailing_spaces() if settings.ADD_NEW_LINE_AT_EOF: editor_widget.insert_block_at_end() # Save content editor_widget.neditable.save_content() # FIXME: encoding message = translations.TR_FILE_SAVED.format(file_path) self.fileSaved.emit(message) return True except Exception as reason: logger.error("Save file error: %s" % reason) QMessageBox.information( self, translations.TR_SAVE_FILE_ERROR_TITLE, translations.TR_SAVE_FILE_ERROR_BODY ) return False def save_file_as(self, editor_widget=None): force = False if editor_widget is None: # We invoque from menu editor_widget = self.get_current_editor() if editor_widget is None: # We haven't editor in main container return False force = True try: filters = "(*.py);;(*.*)" if editor_widget.file_path is not None: # Existing file extension = file_manager.get_file_extension( editor_widget.file_path) if extension != 'py': filters = "(*.%s);;(*.py);;(*.*)" % extension save_folder = self._get_save_folder(editor_widget.file_path) else: save_folder = settings.WORKSPACE filename = QFileDialog.getSaveFileName( self, translations.TR_SAVE_FILE_DIALOG, save_folder, filters )[0] if not filename: return False # FIXME: remove trailing spaces extension = file_manager.get_file_extension(filename) if not extension: filename = "%s.%s" % (filename, "py") editor_widget.neditable.save_content(path=filename, force=force) # self._setter_language.set_language_from_extension(extension) self.fileSaved.emit(translations.TR_FILE_SAVED.format(filename)) self.currentEditorChanged.emit(filename) return True except file_manager.NinjaFileExistsException as reason: QMessageBox.information( self, translations.TR_FILE_ALREADY_EXISTS_TITLE, translations.TR_FILE_ALREADY_EXISTS_BODY.format( reason.filename) ) except Exception as reason: logger.error("Save file as: %s", reason) QMessageBox.information( self, translations.TR_SAVE_FILE_ERROR_TITLE, translations.TR_SAVE_FILE_ERROR_BODY ) return False def save_project(self, project_path): """Save all files in the project path""" for neditable in self.combo_area.bar.get_editables(): file_path = neditable.file_path if file_path is None: # FIXME: New edited files will not be saved, its ok? continue if file_manager.belongs_to_folder(project_path, file_path): neditable.save_content() def _get_save_folder(self, filename): """Returns the root directory of the 'Main Project' or the home folder""" ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() if current_project is not None: return current_project.path return os.path.expanduser("~") def close_file(self): self.combo_area.close_current_file() def add_editor(self, filename=None): ninjaide = IDE.get_service("ide") editable = ninjaide.get_or_create_editable(filename) if editable.editor: # If already open logger.debug("%s is already open" % filename) self.combo_area.set_current(editable) return self.combo_area.current_editor() else: pass editor_widget = self.create_editor_from_editable(editable) # editor_widget.set_language() # Add the tab keep_index = (self.splitter.count() > 1 and self.combo_area.stacked.count() > 0) self.combo_area.add_editor(editable, keep_index) # Emit a signal about the file open self.fileOpened.emit(filename) if keep_index: self.combo_area.set_current(editable) self.stack.setCurrentWidget(self.splitter) editor_widget.setFocus() return editor_widget def create_editor_from_editable(self, editable): neditor = editor.create_editor(editable) neditor.zoomChanged.connect(self._on_zoom_changed) neditor.addBackItemNavigation.connect(self.add_back_item_navigation) editable.fileSaved.connect( lambda neditable: self._explore_file_code(neditable.file_path)) return neditor def add_back_item_navigation(self): editor_widget = self.get_current_editor() if editor_widget is not None: item = (editor_widget.file_path, editor_widget.cursor_position) if item not in self.__code_back: self.__code_back.append(item) # self.__code_forward.clear() def _on_zoom_changed(self, zoom): text = "Zoom: {}%".format(str(zoom)) ide = IDE.get_service("ide") ide.show_message(text) def add_widget(self, widget): self.stack.addWidget(widget) def show_start_page(self): """Show Start Page widget in main container""" startp = self.stack.widget(0) if isinstance(startp, start_page.StartPage): self.stack.setCurrentIndex(0) else: startp = start_page.StartPage(parent=self) startp.newFile.connect(self.add_editor) self.stack.insertWidget(0, startp) self.stack.setCurrentIndex(0) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def add_status_bar(self, status_bar): self._vbox.addWidget(status_bar) def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def restyle_editor(self): neditables = self.combo_area.bar.get_editables() for neditable in neditables: neditable.editor.restyle() def zoom_in_editor(self): """Increase the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(1.) def zoom_out_editor(self): """Decrease the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(-1.) def reset_zoom_editor(self): """Reset the to original font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.reset_zoom() def editor_move_up(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down(up=True) def editor_move_down(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down() def editor_duplicate_line(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.duplicate_line() def editor_toggle_comment(self): """Mark the current line or selection as a comment.""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.comment_or_uncomment() def editor_go_to_line(self, line, column=0, center=True): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.go_to_line(line, column, center) editor_widget.setFocus() def _editor_settings_changed(self, key, value): key = key.split("/")[-1] editor_widget = self.get_current_editor() if editor_widget is not None: callback = getattr(editor.NEditor, key, False) if callback: callback = callback if not hasattr(callback, "__call__"): # Property! callback = callback.fset callback(editor_widget, value) def toggle_tabs_and_spaces(self): """Toggle Show/Hide Tabs and Spaces""" settings.SHOW_TABS_AND_SPACES = not settings.SHOW_TABS_AND_SPACES qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) neditor = self.get_current_editor() if neditor is not None: neditor.show_whitespaces = settings.SHOW_TABS_AND_SPACES def __navigate_with_keyboard(self, forward): """Navigate between the positions in the jump history stack.""" operation = self.combo_area.bar.code_navigator.operation self.navigate_code_history(operation, forward) def navigate_back(self): self.__navigate_with_keyboard(forward=False) def navigate_forward(self): self.__navigate_with_keyboard(forward=True)
class QClickLabel(QWidget): image_show = None # 自定义信号 clicked_signal = pyqtSignal() def __init__(self, parent=None): super(QClickLabel, self).__init__(parent) self.frameShowStackedLayout = QStackedLayout(self) self.frameShowStackedLayout.setObjectName("frameShowStackedLayout") self.frameShowStackedLayout.setStackingMode(1) self.StopBox = QLabel(self) self.StopBox.setStyleSheet( "background-color: rgba(222, 222, 222, 0);background-image: url(:/system/img/play.png);background-repeat: no-repeat;background-position: center center;" ) self.StopBox.setText("") self.frameShowStackedLayout.addWidget(self.StopBox) self.ImageBox = QLabel(self) self.ImageBox.setStyleSheet("background-color: #242423;") self.ImageBox.setText("") sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.ImageBox.sizePolicy().hasHeightForWidth()) self.ImageBox.setSizePolicy(sizePolicy) self.ImageBox.setMinimumSize(QSize(200, 200)) self.ImageBox.setScaledContents(False) self.ImageBox.setAlignment(Qt.AlignCenter) self.frameShowStackedLayout.addWidget(self.ImageBox) # 鼠标点击事件 def mouseReleaseEvent(self, QMouseEvent): self.clicked_signal.emit() # 可在外部与槽函数连接 def clicked(self, func): self.clicked_signal.connect(func) # 格式化图像为当前容器大小 def __formatImage(self, image): w1 = image.width() h1 = image.height() w2 = self.width() h2 = self.height() if w1 > h1: return image.scaled(w2, w2 / w1 * h1, Qt.KeepAspectRatio) return image.scaled(h2 / h1 * w1, h2, Qt.KeepAspectRatio) def setPixmap(self, image): if image == None: self.frameShowStackedLayout.setCurrentIndex(0) else: self.image_show = image self.frameShowStackedLayout.setCurrentIndex(1) self.ImageBox.setPixmap( QPixmap.fromImage(self.__formatImage(image))) def resizeEvent(self, event): if self.image_show != None: self.setPixmap(self.image_show) self.setPixmap(None)
class _MainContainer(QWidget): ############################################################################### # MainContainer SIGNALS ############################################################################### """ newFileOpened(QString) allTabClosed() runFile(QString) addToProject(QString) showFileInExplorer(QString) recentTabsModified() currentEditorChanged(QString) fileOpened(QString) ---------migrationAnalyzed() findOcurrences(QString) ---------updateFileMetadata() editorKeyPressEvent(QEvent) locateFunction(QString, QString, bool) [functionName, filePath, isVariable] updateLocator(QString) beforeFileSaved(QString) fileSaved(QString) openPreferences() --------openProject(QString) ---------dontOpenStartPage() """ ############################################################################### fileOpened = pyqtSignal('QString') updateLocator = pyqtSignal('QString') currentEditorChanged = pyqtSignal('QString') beforeFileSaved = pyqtSignal('QString') fileSaved = pyqtSignal('QString') def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self.setContentsMargins(0, 0, 0, 0) self._parent = parent self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) # self._files_handler = files_handler.FilesHandler(self) self._add_file_folder = add_file_folder.AddFileFolderWidget(self) # documentation browser self.docPage = None # Code Navigation # self._locator = locator.GoToDefinition() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints } # self.locateFunction['QString', # 'QString', # bool].connect(self.locate_function) IDE.register_service('main_container', self) # Register signals connections connections = ({ 'target': 'main_container', 'signal_name': 'updateLocator', 'slot': self._explore_file_code }, { 'target': 'filesystem', 'signal_name': 'projectOpened', 'slot': self._explore_code }, { 'target': 'projects_explorer', 'signal_name': 'updateLocator', 'slot': self._explore_code }) """ {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, {'target': 'filesystem', 'signal_name': 'projectOpened', 'slot': self._explore_code}, {'target': 'main_container', 'signal_name': 'updateLocator(QString)', 'slot': self._explore_file_code}, ) """ IDE.register_signals('main_container', connections) self.selector = main_selector.MainSelector(self) self._opening_dialog = False self.add_widget(self.selector) if settings.SHOW_START_PAGE: self.show_start_page() self.selector.changeCurrent[int].connect(self._change_current_stack) # self.selector.removeWidget[int].connect(self._remove_item_from_stack) # self.selector.ready.connect(self._selector_ready) self.selector.animationCompleted.connect( self._selector_animation_completed) # self.closeDialog['PyQt_PyObject'].connect(self.remove_widget) def install(self): ide = IDE.get_service('ide') ide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.combo_area.allFilesClosed.connect(self._files_closed) # self.combo_area.allFilesClosed.connect(self._files_closed) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) self.current_widget = self.combo_area # Code Locator self._code_locator = locator_widget.LocatorWidget(ide) ui_tools.install_shortcuts(self, actions.ACTIONS, ide) def show_locator(self): """Show the locator widget""" if not self._code_locator.isVisible(): self._code_locator.show() def _explore_code(self): """ Update locator metadata for the current projects """ self._code_locator.explore_code() def _explore_file_code(self, path): """ Update locator metadata for the file in path """ self._code_locator.explore_file_code(path) def add_status_bar(self, status): self._vbox.addWidget(status) @property def combo_header_size(self): return self.combo_area.bar.height() def add_widget(self, widget): self.stack.addWidget(widget) def remove_widget(self, widget): self.stack.removeWidget(widget) def _close_dialog(self, widget): self.emit(SIGNAL("closeDialog(PyQt_PyObject)"), widget) self.disconnect(widget, SIGNAL("finished(int)"), lambda: self._close_dialog(widget)) def show_dialog(self, widget): self._opening_dialog = True # self.connect(widget, SIGNAL("finished(int)"), # lambda: self._close_dialog(widget)) self.setVisible(True) self.stack.addWidget(widget) self.show_selector() def show_selector(self): if self.selector != self.stack.currentWidget(): temp_dir = os.path.join(QDir.tempPath(), "ninja-ide") if not os.path.exists(temp_dir): os.mkdir(temp_dir) collected_data = [] current = self.stack.currentIndex() for index in range(self.stack.count()): widget = self.stack.widget(index) if widget == self.selector: continue pixmap = QWidget.grab(widget, widget.rect()) path = os.path.join(temp_dir, "screen%s.png" % index) pixmap.save(path) collected_data.append((index, path)) self.selector.set_model(collected_data) self._selector_ready() """ if self.selector != self.stack.currentWidget(): temp_dir = os.path.join(QDir.tempPath(), "ninja-ide") if not os.path.exists(temp_dir): os.mkdir(temp_dir) collected_data = [] current = self.stack.currentIndex() for index in range(self.stack.count()): widget = self.stack.widget(index) if widget == self.selector: continue closable = True if widget == self.splitter: closable = False pixmap = QWidget.grab(widget, widget.rect()) path = os.path.join(temp_dir, "screen%s.png" % index) pixmap.save(path) if index == current: self.selector.set_preview(index, path) collected_data.insert(0, (index, path, closable)) else: collected_data.append((index, path, closable)) self.selector.set_model(collected_data) else: self.selector.close_selector() """ def _selector_ready(self): print(self.stack.currentWidget()) self.stack.setCurrentWidget(self.selector) print(self.stack.currentWidget()) self.selector.start_animation() def _selector_animation_completed(self): if self._opening_dialog: # We choose the last one with -2, -1 (for last one) + # -1 for the hidden selector widget which is in the stacked too. self.selector.open_item(self.stack.count() - 2) self._opening_dialog = False def _change_current_stack(self, index): self.stack.setCurrentIndex(index) def _remove_item_from_stack(self, index): widget = self.stack.takeAt(index) del widget def show_editor_area(self): self.stack.setCurrentWidget(self.splitter) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def change_visibility(self): """Show/Hide the Main Container area.""" if self.isVisible(): self.hide() else: self.show() def expand_symbol_combo(self): self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_symbol() def expand_file_combo(self): self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_file() def locate_function(self, function, filePath, isVariable): """Move the cursor to the proper position in the navigate stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append( (editorWidget.file_path, editorWidget.getCursorPosition())) self.__codeForward = [] self._locator.navigate_to(function, filePath, isVariable) def run_file(self, path): self.emit(SIGNAL("runFile(QString)"), path) def _add_to_project(self, path): self.emit(SIGNAL("addToProject(QString)"), path) def _show_file_in_explorer(self, path): self.emit(SIGNAL("showFileInExplorer(QString)"), path) def paste_history(self): """Paste the text from the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): line, index = editorWidget.getCursorPosition() central = IDE.get_service('central_container') if central: editorWidget.insertAt(central.get_paste(), line, index) def copy_history(self): """Copy the selected text into the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): copy = editorWidget.selectedText() central = IDE.get_service('central_container') if central: central.add_copy(copy) def import_from_everywhere(self): """Insert an import line from any place in the editor.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def add_back_item_navigation(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append( (editorWidget.file_path, editorWidget.cursor_position)) self.__codeForward = [] def preview_in_browser(self): """Load the current html file in the default browser.""" editorWidget = self.get_current_editor() if editorWidget: if not editorWidget.file_path: self.save_file() ext = file_manager.get_file_extension(editorWidget.file_path) if ext in ('html', 'shpaml', 'handlebars', 'tpl'): webbrowser.open_new_tab(editorWidget.file_path) def add_bookmark_breakpoint(self): """Add a bookmark or breakpoint to the current file in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): if self.current_widget.bar.code_navigator.operation == 1: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.ControlModifier) elif self.current_widget.bar.code_navigator.operation == 2: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.NoModifier) def __navigate_with_keyboard(self, val): """Navigate between the positions in the jump history stack.""" op = self.current_widget.bar.code_navigator.operation self.navigate_code_history(val, op) def navigate_code_history(self, val, op): """Navigate the code history.""" self.__operations[op](val) def _navigate_code_jumps(self, val): """Navigate between the jump points.""" node = None if not val and self.__codeBack: node = self.__codeBack.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeForward.append( (editorWidget.file_path, editorWidget.getCursorPosition())) elif val and self.__codeForward: node = self.__codeForward.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append( (editorWidget.file_path, editorWidget.getCursorPosition())) if node: filename = node[0] line, col = node[1] self.open_file(filename, line, col) def _navigate_breakpoints(self, val): """Navigate between the breakpoints.""" # FIXME: put navigate breakpoints and bookmarks as one method. breakList = list(settings.BREAKPOINTS.keys()) breakList.sort() if not breakList: return if self.__breakpointsFile not in breakList: self.__breakpointsFile = breakList[0] index = breakList.index(self.__breakpointsFile) breaks = settings.BREAKPOINTS.get(self.__breakpointsFile, []) lineNumber = 0 # val == True: forward if val: if (len(breaks) - 1) > self.__breakpointsPos: self.__breakpointsPos += 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: if index < (len(breakList) - 1): self.__breakpointsFile = breakList[index + 1] else: self.__breakpointsFile = breakList[0] self.__breakpointsPos = 0 lineNumber = settings.BREAKPOINTS[self.__breakpointsFile][0] else: if self.__breakpointsPos > 0: self.__breakpointsPos -= 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: self.__breakpointsFile = breakList[index - 1] breaks = settings.BREAKPOINTS[self.__breakpointsFile] self.__breakpointsPos = len(breaks) - 1 lineNumber = breaks[self.__breakpointsPos] if file_manager.file_exists(self.__breakpointsFile): self.open_file(self.__breakpointsFile, lineNumber, None, True) else: settings.BREAKPOINTS.pop(self.__breakpointsFile) if settings.BREAKPOINTS: self._navigate_breakpoints(val) def _navigate_bookmarks(self, val): """Navigate between the bookmarks.""" bookList = list(settings.BOOKMARKS.keys()) bookList.sort() if not bookList: return if self.__bookmarksFile not in bookList: self.__bookmarksFile = bookList[0] index = bookList.index(self.__bookmarksFile) bookms = settings.BOOKMARKS.get(self.__bookmarksFile, []) lineNumber = 0 # val == True: forward if val: if (len(bookms) - 1) > self.__bookmarksPos: self.__bookmarksPos += 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: if index < (len(bookList) - 1): self.__bookmarksFile = bookList[index + 1] else: self.__bookmarksFile = bookList[0] self.__bookmarksPos = 0 lineNumber = settings.BOOKMARKS[self.__bookmarksFile][0] else: if self.__bookmarksPos > 0: self.__bookmarksPos -= 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: self.__bookmarksFile = bookList[index - 1] bookms = settings.BOOKMARKS[self.__bookmarksFile] self.__bookmarksPos = len(bookms) - 1 lineNumber = bookms[self.__bookmarksPos] if file_manager.file_exists(self.__bookmarksFile): self.open_file(self.__bookmarksFile, lineNumber, None, True) else: # settings.BOOKMARKS.pop(self.__bookmarksFile) if settings.BOOKMARKS: self._navigate_bookmarks(val) def count_file_code_lines(self): """Count the lines of code in the current file.""" editorWidget = self.get_current_editor() if editorWidget: block_count = editorWidget.lines() blanks = re.findall('(^\n)|(^(\s+)?#)|(^( +)?($|\n))', editorWidget.text(), re.M) blanks_count = len(blanks) resume = self.tr("Lines code: %s\n") % (block_count - blanks_count) resume += (self.tr("Blanks and commented lines: %s\n\n") % blanks_count) resume += self.tr("Total lines: %s") % blockdget msgBox.exec_() msgBox = QMessageBox(QMessageBox.Information, self.tr("Summary of lines"), resume, QMessageBox.Ok, editorWidget) def editor_cut(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.cut() def editor_copy(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.copy() def editor_paste(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.paste() def editor_upper(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_upper() def editor_lower(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_lower() def editor_title(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_title() def editor_go_to_definition(self): """Search the definition of the method or variable under the cursor. If more than one method or variable is found with the same name, shows a table with the results and let the user decide where to go.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.go_to_definition() def editor_redo(self): """Execute the redo action in the current editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.redo() def editor_undo(self): editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.undo() def editor_indent_less(self): """Indent 1 position to the left for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_less() def editor_indent_more(self): """Indent 1 position to the right for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_more() def editor_insert_debugging_prints(self): """Insert a print statement in each selected line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_debugging_prints(editorWidget) def editor_insert_pdb(self): """Insert a pdb.set_trace() statement in tjhe current line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_pdb(editorWidget) def editor_comment(self): """Mark the current line or selection as a comment.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.comment_or_uncomment(editorWidget) def editor_uncomment(self): """Uncomment the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.uncomment(editorWidget) def editor_insert_horizontal_line(self): """Insert an horizontal lines of comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_horizontal_line(editorWidget) def editor_insert_title_comment(self): """Insert a Title surrounded by comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_title_comment(editorWidget) def editor_remove_trailing_spaces(self): """Remove the trailing spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.remove_trailing_spaces(editorWidget) def editor_replace_tabs_with_spaces(self): """Replace the Tabs with Spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.replace_tabs_with_spaces(editorWidget) def editor_move_up(self): """Move the current line or selection one position up.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_up(editorWidget) def editor_move_down(self): """Move the current line or selection one position down.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_down(editorWidget) def editor_remove_line(self): """Remove the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.remove_line(editorWidget) def editor_duplicate(self): """Duplicate the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.duplicate(editorWidget) def editor_highlight_word(self): """Highlight the occurrences of the current word in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.highlight_selected_word() def editor_complete_declaration(self): """Do the opposite action that Complete Declaration expect.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.complete_declaration() def editor_go_to_line(self, line): """ Jump to the specified line in the current editor. """ editorWidget = self.get_current_editor() if editorWidget: editorWidget.go_to_line(line) editorWidget.setFocus() def zoom_in_editor(self): """Increase the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom(1.0) def zoom_out_editor(self): """Decrease the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom(-1.0) def reset_zoom(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.reset_zoom() def recent_files_changed(self): self.emit(SIGNAL("recentTabsModified()")) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): file_path = event.mimeData().urls()[0].toLocalFile() self.open_file(file_path) def setFocus(self): widget = self.get_current_widget() if widget: widget.setFocus() def current_editor_changed(self, filename): """Notify the new filename of the current editor.""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.currentEditorChanged.emit(filename) def show_split(self, orientation_vertical=False): # IDE.select_current(self.current_widget.currentWidget()) self.current_widget.split_editor(orientation_vertical) def add_editor(self, fileName=None, ignore_checkers=False): ninjaide = IDE.get_service('ide') editable = ninjaide.get_or_create_editable(fileName) if editable.editor: self.current_widget.set_current(editable) return self.current_widget.currentWidget() else: editable.ignore_checkers = ignore_checkers editorWidget = self.create_editor_from_editable(editable) # add the tab keep_index = (self.splitter.count() > 1 and self.combo_area.stacked.count() > 0) self.combo_area.add_editor(editable, keep_index) # emit a signal about the file open self.fileOpened.emit(fileName) if not keep_index: self.current_widget.set_current(editable) self.stack.setCurrentWidget(self.splitter) editorWidget.setFocus() return editorWidget def create_editor_from_editable(self, editable): neditor = editor.create_editor(editable) # Connect signals neditor.zoomChanged[int].connect(self._show_zoom_indicator) neditor.destroyed.connect(self._editor_destroyed) editable.fileSaved.connect(self._editor_tab_was_saved) neditor.addBackItemNavigation.connect(self.add_back_item_navigation) # self.connect(editable, SIGNAL("fileSaved(PyQt_PyObject)"), # self._editor_tab_was_saved) # editorWidget.font_changed.connect(self.show_zoom_indicator) # self.connect(editorWidget, SIGNAL("openDropFile(QString)"), # self.open_file) # self.connect(editorWidget, SIGNAL("addBackItemNavigation()"), # self.add_back_item_navigation) # self.connect(editorWidget, # SIGNAL("locateFunction(QString, QString, bool)"), # self._editor_locate_function) # self.connect(editorWidget, SIGNAL("findOcurrences(QString)"), # self._find_occurrences) # keyPressEventSignal for plugins # self.connect(editorWidget, SIGNAL("keyPressEvent(QEvent)"), # self._editor_keyPressEvent) return neditor def _editor_destroyed(self): ui_tools.FadingIndicator.editor_destroyed() def _show_zoom_indicator(self, text): neditor = self.get_current_editor() ui_tools.FadingIndicator.show_text(neditor, "Zoom: {}%".format(str(text))) def reset_pep8_warnings(self, value): pass # FIXME: check how we handle this # for i in range(self._tabMain.count()): # widget = self._tabMain.widget(i) # if type(widget) is editor.Editor: # if value: # widget.syncDocErrorsSignal = True # widget.pep8.check_style() # else: # widget.hide_pep8_errors() def reset_lint_warnings(self, value): pass #FIXME: check how we handle this # for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() def show_zoom_indicator(self, text): ui_tools.FadingIndicator.show_text(self, "Zoom: {0}%".format(text)) def _find_occurrences(self, word): self.emit(SIGNAL("findOcurrences(QString)"), word) def _editor_keyPressEvent(self, event): self.emit(SIGNAL("editorKeyPressEvent(QEvent)"), event) def _editor_locate_function(self, function, filePath, isVariable): self.emit(SIGNAL("locateFunction(QString, QString, bool)"), function, filePath, isVariable) def _editor_tab_was_saved(self, editable=None): self.updateLocator.emit(editable.file_path) # self.emit(SIGNAL("updateLocator(QString)"), editable.file_path) def get_current_widget(self): return self.current_widget.currentWidget() def get_current_editor(self): """Return the Actual Editor or None Return an instance of Editor if the Current Tab contains an Editor or None if it is not an instance of Editor""" widget = self.current_widget.currentWidget() if isinstance(widget, editor.NEditor): return widget return None def reload_file(self, editorWidget=None): if editorWidget is None: editorWidget = self.get_current_editor() editorWidget.neditable.reload_file() def open_image(self, fileName): try: if not self.is_open(fileName): viewer = image_viewer.ImageViewer(fileName) # self.add_tab(viewer, file_manager.get_basename(fileName)) # viewer.ID = fileName else: self.move_to_open(fileName) except Exception as reason: logger.error('open_image: %s', reason) QMessageBox.information(self, self.tr("Incorrect File"), self.tr("The image couldn\'t be open")) def open_file(self, filename='', line=-1, col=0, ignore_checkers=False): logger.debug("will try to open %s" % filename) if not filename: logger.debug("has nofilename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editorWidget = self.get_current_editor() ninjaide = IDE.get_service('ide') if ninjaide: current_project = ninjaide.get_current_project() if current_project is not None: directory = current_project elif editorWidget is not None and editorWidget.file_path: directory = file_manager.get_folder( editorWidget.file_path) extensions = ';;'.join([ '{}(*{})'.format(e.upper()[1:], e) for e in settings.SUPPORTED_EXTENSIONS + ['.*', ''] ]) fileNames = QFileDialog.getOpenFileNames(self, self.tr("Open File"), directory, extensions)[0] else: logger.debug("has filename") fileNames = [filename] if not fileNames: return for filename in fileNames: image_extensions = ('bmp', 'gif', 'jpeg', 'jpg', 'png') if file_manager.get_file_extension(filename) in image_extensions: logger.debug("will open as image") self.open_image(filename) elif file_manager.get_file_extension(filename).endswith('ui'): logger.debug("will load in ui editor") self.w = uic.loadUi(filename) self.w.show() else: logger.debug("will try to open: " + filename) self.__open_file(filename, line, col, ignore_checkers) def __open_file(self, fileName='', line=-1, col=0, ignore_checkers=False): try: editorWidget = self.add_editor(fileName, ignore_checkers=ignore_checkers) if line != -1: editorWidget.go_to_line(line, col) self.currentEditorChanged.emit(fileName) except file_manager.NinjaIOException as reason: QMessageBox.information(self, self.tr("The file couldn't be open"), str(reason)) def is_open(self, filename): pass #return self.tabs.is_open(filename) != -1 def move_to_open(self, filename): pass #FIXME: add in the current split? #if self.tabs.is_open(filename) != -1: #self.tabs.move_to_open(filename) #self.tabs.currentWidget().setFocus() #self.emit(SIGNAL("currentEditorChanged(QString)"), filename) def get_widget_for_id(self, filename): pass #widget = None #index = self.tabs.is_open(filename) #if index != -1: #widget = self.tabs.widget(index) #return widget def change_open_tab_id(self, idname, newId): """Search for the Tab with idname, and set the newId to that Tab.""" pass #index = self.tabs.is_open(idname) #if index != -1: #widget = self.tabs.widget(index) #tabName = file_manager.get_basename(newId) #self.tabs.change_open_tab_name(index, tabName) #widget.ID = newId def close_deleted_file(self, idname): """Search for the Tab with id, and ask the user if should be closed.""" pass #index = self.tabs.is_open(idname) #if index != -1: #result = QMessageBox.question(self, self.tr("Close Deleted File"), #self.tr("Are you sure you want to close the deleted file?\n" #"The content will be completely deleted."), #buttons=QMessageBox.Yes | QMessageBox.No) #if result == QMessageBox.Yes: #self.tabs.removeTab(index) def save_file(self, editorWidget=None): # FIXME: check how we handle this if not editorWidget: editorWidget = self.get_current_editor() if editorWidget is None: return False # Ok, we have an editor instance # Save to file only if editor really was modified if editorWidget.is_modified: try: if (editorWidget.nfile.is_new_file or not editorWidget.nfile.has_write_permission()): return self.save_file_as() self.beforeFileSaved.emit(editorWidget.file_path) if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) # New line at end # FIXME: from settings helpers.insert_block_at_end(editorWidget) # Save convent editorWidget.neditable.save_content() encoding = file_manager.get_file_encoding(editorWidget.text) editorWidget.encoding = encoding self.fileSaved.emit( self.tr("File Saved: {}".format(editorWidget.file_path))) return True except Exception as reason: logger.error('save_file: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def save_file_as(self): editorWidget = self.get_current_editor() if not editorWidget: return False try: filters = '(*.py);;(*.*)' if editorWidget.file_path: # existing file ext = file_manager.get_file_extension(editorWidget.file_path) if ext != 'py': filters = '(*.%s);;(*.py);;(*.*)' % ext save_folder = self._get_save_folder(editorWidget.file_path) fileName = QFileDialog.getSaveFileName(self._parent, self.tr("Save File"), save_folder, filters)[0] if not fileName: return False if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) ext = file_manager.get_file_extension(fileName) if not ext: fileName = '%s.%s' % ( fileName, 'py', ) editorWidget.neditable.save_content(path=fileName) # editorWidget.register_syntax( # file_manager.get_file_extension(fileName)) self.fileSaved.emit(self.tr("File Saved: {}".format(fileName))) self.currentEditorChanged.emit(fileName) return True except file_manager.NinjaFileExistsException as ex: QMessageBox.information( self, self.tr("File Already Exists"), (self.tr("Invalid Path: the file '%s' " " already exists.") % ex.filename)) except Exception as reason: logger.error('save_file_as: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def _get_save_folder(self, fileName): """ Returns the root directory of the 'Main Project' or the home folder """ ninjaide = IDE.get_service('ide') current_project = ninjaide.get_current_project() if current_project: return current_project.path return os.path.expanduser("~") def save_project(self, projectFolder): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def save_all(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor: #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #self.tabsecondary.check_for_external_modifications(editorWidget) #if type(editorWidget) is editor.Editor: #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def call_editors_function(self, call_function, *arguments): pass #args = arguments[0] #kwargs = arguments[1] #for i in range(self.tabs.count()): #editorWidget = self.tabs.widget(i) #if isinstance(editorWidget, editor.Editor): #function = getattr(editorWidget, call_function) #function(*args, **kwargs) #TODO: add other splits def show_start_page(self): start = self.stack.widget(0) if isinstance(start, start_page.StartPage): self.stack.setCurrentIndex(0) else: startPage = start_page.StartPage(parent=self) # self.connect(startPage, SIGNAL("openProject(QString)"), # self.open_project) # self.connect(startPage, SIGNAL("openPreferences()"), # lambda: self.emit(SIGNAL("openPreferences()"))) # Connections startPage.newFile.connect(self.add_editor) self.stack.insertWidget(0, startPage) self.stack.setCurrentIndex(0) def show_python_doc(self): if sys.platform == 'win32': self.docPage = browser_widget.BrowserWidget( 'http://docs.python.org/') else: process = runner.start_pydoc() self.docPage = browser_widget.BrowserWidget(process[1], process[0]) self.add_tab(self.docPage, translations.TR_PYTHON_DOC) def show_report_bugs(self): webbrowser.open(resources.BUGS_PAGE) def show_plugins_doc(self): bugsPage = browser_widget.BrowserWidget(resources.PLUGINS_DOC, self) self.add_tab(bugsPage, translations.TR_HOW_TO_WRITE_PLUGINS) def editor_jump_to_line(self, lineno=None): """Jump to line *lineno* if it is not None otherwise ask to the user the line number to jump """ editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(lineno=lineno) def get_opened_documents(self): #return self.tabs.get_documents_data() return [] def check_for_unsaved_files(self): pass #return self.tabs._check_unsaved_tabs() def get_unsaved_files(self): pass #return self.tabs.get_unsaved_files() def reset_editor_flags(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.set_flags() def _specify_syntax(self, widget, syntaxLang): if isinstance(widget, editor.Editor): widget.restyle(syntaxLang) def apply_editor_theme(self, family, size): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.restyle() #widget.set_font(family, size) def update_editor_margin_line(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget._update_margin_line() def open_project(self, path): self.emit(SIGNAL("openProject(QString)"), path) def close_python_doc(self): pass # close the python document server (if running) # if self.docPage: # index = self.tabs.indexOf(self.docPage) # self.tabs.removeTab(index) # assign None to the browser # self.docPage = None def close_file(self): self.current_widget.close_current_file() def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def change_tab(self): """Change the tab in the current TabWidget.""" self.stack.setCurrentWidget(self.splitter) # self._files_handler.next_item() def change_tab_reverse(self): """Change the tab in the current TabWidget backwards.""" self.stack.setCurrentWidget(self.splitter) # self._files_handler.previous_item() def toggle_tabs_and_spaces(self): """Toggle Show/Hide Tabs and Spaces""" settings.SHOW_TABS_AND_SPACES = not settings.SHOW_TABS_AND_SPACES qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/show_tabs_and_spaces', settings.SHOW_TABS_AND_SPACES) neditor = self.get_current_editor() if neditor is not None: neditor.show_whitespaces = settings.SHOW_TABS_AND_SPACES def show_navigation_buttons(self): """Show Navigation menu.""" self.stack.setCurrentWidget(self.splitter) self.combo_area.show_menu_navigation() def change_split_focus(self): pass #FIXME: check how we handle this #if self.actualTab == self._tabMain and self.tabsecondary.isVisible(): #self.actualTab = self.tabsecondary #else: #self.actualTab = self._tabMain #widget = self.actualTab.currentWidget() #if widget is not None: #widget.setFocus() def shortcut_index(self, index): pass #self.tabs.setCurrentIndex(index) def print_file(self): """Call the print of ui_tool Call print of ui_tool depending on the focus of the application""" #TODO: Add funtionality for proyect tab and methods tab editorWidget = self.get_current_editor() if editorWidget is not None: fileName = "newDocument.pdf" if editorWidget.file_path: fileName = file_manager.get_basename(editorWidget.file_path) fileName = fileName[:fileName.rfind('.')] + '.pdf' ui_tools.print_file(fileName, editorWidget.print_) def split_assistance(self): dialog = split_orientation.SplitOrientation(self) dialog.show() # def close_split(self): # if self.current_widget != self.combo_area: # self.current_widget.bar.close_split() # def split_vertically(self): # self.show_split(False) # def split_horizontally(self): # self.show_split(True) def navigate_back(self): self.__navigate_with_keyboard(False) def navigate_forward(self): self.__navigate_with_keyboard(True)
class _MainContainer(QWidget): currentEditorChanged = pyqtSignal("QString") fileOpened = pyqtSignal("QString") fileSaved = pyqtSignal("QString") def __init__(self, parent=None): super().__init__(parent) self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) # QML UI self._add_file_folder = add_file_folder.AddFileFolderWidget(self) if settings.SHOW_START_PAGE: self.show_start_page() IDE.register_service("main_container", self) # Register signals connections connections = ({ "target": "main_container", "signal_name": "updateLocator", "slot": self._explore_code }, { "target": "filesystem", "signal_name": "projectOpened", "slot": self._explore_code }, { "target": "projects_explore", "signal_name": "updateLocator", "slot": self._explore_code }) IDE.register_signals("main_container", connections) esc_sort = QShortcut(QKeySequence(Qt.Key_Escape), self) esc_sort.activated.connect(self._set_focus_to_editor) def install(self): ninjaide = IDE.get_service("ide") ninjaide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.combo_area.allFilesClosed.connect(self._files_closed) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) self.current_widget = self.combo_area # Code Locator self._code_locator = locator_widget.LocatorWidget(ninjaide) ui_tools.install_shortcuts(self, actions.ACTIONS, ninjaide) def _set_focus_to_editor(self): status_bar = IDE.get_service("status_bar") tools_doock = IDE.get_service("tools_dock") editor_widget = self.get_current_editor() if status_bar.isVisible() and tools_doock.isVisible(): status_bar.hide_status_bar() elif tools_doock.isVisible(): tools_doock._hide() elif status_bar.isVisible(): status_bar.hide_status_bar() if editor_widget is not None: editor_widget.clear_extra_selections('searchs') def split_assistance(self): split_widget = split_orientation.SplitOrientation(self) split_widget.show() def show_split(self, orientation_vertical=False): self.current_widget.split_editor(orientation_vertical) def show_locator(self): """Show the Locator Widget""" if not self._code_locator.isVisible(): self._code_locator.show() def _explore_code(self): """Update locator metadata for the current projects""" self._code_locator.explore_code() def current_editor_changed(self, filename): """Notify the new filename of the current editor""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.currentEditorChanged.emit(filename) def get_current_editor(self): current_widget = self.current_widget.currentWidget() if isinstance(current_widget, editor.NEditor): return current_widget return None def open_file(self, filename='', line=-1, col=0): logger.debug("Will try to open %s" % filename) if not filename: logger.debug("Has no filename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editor_widget = self.get_current_editor() ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() # TODO: handle current project in NProject if current_project is not None: directory = current_project.full_path elif editor_widget is not None and editor_widget.file_path: directory = file_manager.get_folder( editor_widget.file_path) extensions = ";;".join([ "{}(*{})".format(e.upper()[1:], e) for e in settings.SUPPORTED_EXTENSIONS + [".*", ""] ]) filenames = QFileDialog.getOpenFileNames( self, "Open File", # FIXME: translations directory, extensions)[0] else: logger.debug("Has filename") filenames = [filename] if not filenames: return for filename in filenames: logger.debug("Will try to open: %s" % filename) self.__open_file(filename, line, col) def __open_file(self, filename, line, col): try: editor_widget = self.add_editor(filename) if line != -1: editor_widget.go_to_line(line, col) self.currentEditorChanged.emit(filename) except file_manager.NinjaIOException as reason: QMessageBox.information( self, "The file couldn't be open", # FIXME: translations str(reason)) logger.error("The file %s couldn't be open" % filename) def save_file(self, editor_widget=None): if editor_widget is None: # This may return None if there is not editor present editor_widget = self.get_current_editor() if editor_widget is None: return False # Ok, we have an editor instance # Save to file only if editor really was modified if editor_widget.is_modified: try: if editor_widget.nfile.is_new_file or \ not editor_widget.nfile.has_write_permission(): return self.save_file_as(editor_widget) # FIXME: beforeFileSaved.emit if settings.REMOVE_TRAILING_SPACES: pass # FIXME: new line at end # Save content editor_widget.neditable.save_content() # FIXME: encoding # FIXME: translations self.fileSaved.emit("File Saved: %s" % editor_widget.file_path) return True except Exception as reason: logger.error("Save file error: %s" % reason) QMessageBox.information(self, "Save Error", "The file could't be saved!") return False def save_file_as(self, editor_widget=None): force = False if editor_widget is None: # We invoque from menu editor_widget = self.get_current_editor() if editor_widget is None: # We haven't editor in main container return False force = True try: filters = "(*.py);;(*.*)" if editor_widget.file_path is not None: # Existing file extension = file_manager.get_file_extension( editor_widget.file_path) if extension != 'py': filters = "(*.%s);;(*.py);;(*.*)" % extension save_folder = self._get_save_folder(editor_widget.file_path) filename = QFileDialog.getSaveFileName(self, "Save File", save_folder, filters)[0] if not filename: return False # FIXME: remove trailing spaces extension = file_manager.get_file_extension(filename) if not extension: filename = "%s.%s" % (filename, "py") editor_widget.neditable.save_content(path=filename, force=force) self.fileSaved.emit("File Saved: {}".format(filename)) self.currentEditorChanged.emit(filename) return True except file_manager.NinjaFileExistsException as reason: QMessageBox.information( self, "File Already Exists", "Invalid Path: the file '%s' already exists." % reason.filename) except Exception as reason: logger.error("save_file_as: %s", reason) QMessageBox.information(self, "Save Error", "The file couldn't be saved!") return False def _get_save_folder(self, filename): """Returns the root directory of the 'Main Project' or the home folder""" ninjaide = IDE.get_service("ide") current_project = ninjaide.get_current_project() if current_project is not None: return current_project.path return os.path.expanduser("~") def close_file(self): self.current_widget.close_current_file() def add_editor(self, filename=None): ninjaide = IDE.get_service("ide") editable = ninjaide.get_or_create_editable(filename) if editable.editor: # If already open logger.debug("%s is already open" % filename) self.current_widget.set_current(editable) return self.current_widget.currentWidget() else: pass editor_widget = self.create_editor_from_editable(editable) # editor_widget.set_language() # Add the tab keep_index = (self.splitter.count() > 1 and self.combo_area.stacked.count() > 0) self.combo_area.add_editor(editable, keep_index) # Emit a signal about the file open self.fileOpened.emit(filename) if not keep_index: self.current_widget.set_current(editable) self.stack.setCurrentWidget(self.splitter) editor_widget.setFocus() return editor_widget def create_editor_from_editable(self, editable): neditor = editor.create_editor(editable) neditor.zoomChanged.connect(self._show_zoom_indicator) neditor.destroyed.connect(self.__on_editor_destroyed) # editable.fileSaved.connect(self._editor_tab) return neditor def _show_zoom_indicator(self, zoom): neditor = self.get_current_editor() indicator.Indicator.show_text(neditor, "Zoom: {} %".format(str(zoom))) @pyqtSlot() def __on_editor_destroyed(self): indicator.Indicator.instance = None def add_widget(self, widget): self.stack.addWidget(widget) def show_start_page(self): """Show Start Page widget in main container""" startp = self.stack.widget(0) if isinstance(startp, start_page.StartPage): self.stack.setCurrentIndex(0) else: startp = start_page.StartPage(parent=self) startp.newFile.connect(self.add_editor) self.stack.insertWidget(0, startp) self.stack.setCurrentIndex(0) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def add_status_bar(self, status_bar): self._vbox.addWidget(status_bar) def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def zoom_in_editor(self): """Increase the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(1.) def zoom_out_editor(self): """Decrease the font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.zoom(-1.) def reset_zoom_editor(self): """Reset the to original font size in the current editor""" editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.reset_zoom() def editor_move_up(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down(up=True) def editor_move_down(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.move_up_down() def editor_duplicate_line(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.duplicate_line() def editor_comment(self): editor_widget = self.get_current_editor() if editor_widget is not None: editor_widget.comment()
class DualScale(QWidget): def __init__(self, parent=None, in_designer=False): QWidget.__init__(self, parent=parent) self.in_designer = in_designer self.d_vertically_flipped = False self.ui = epyqlib.dualscale_ui.Ui_Form() self.ui.setupUi(self) self.scale1 = epyqlib.widgets.scale.Scale(self, in_designer) self.scale2 = epyqlib.widgets.scale.Scale(self, in_designer) # color ranges, scale markers, labels, needle painted. self.scale1.ui.scale.m_paintMode = 1 # needle, cover painted. self.scale2.ui.scale.m_paintMode = 3 # scale2's needle is blue self.scale2.ui.scale.isBlue = True self.stackedLayout = QStackedLayout() self.stackedLayout.addWidget(self.scale2) self.stackedLayout.addWidget(self.scale1) self.stackedLayout.setStackingMode(1) self.ui.glayout.addLayout(self.stackedLayout, 0, 0) # Trying to figure out how to get lower min and the higher max and change the scale # true_min = min(self.scale1.ui.scale.m_minimum, self.scale2.ui.scale.m_minimum) # true_max = max(self.scale1.ui.scale.m_maximum, self.scale2.ui.scale.m_maximum) # self.scale1.minimum = true_min # self.scale2.minimum = true_min # self.scale1.maximum = true_max # self.scale2.maximum = true_max # self.scale1.override_range = True # self.scale2.override_range = True @pyqtProperty("QString") def scale1_signal_path(self): return self.scale1.signal_path @scale1_signal_path.setter def scale1_signal_path(self, value): self.scale1.signal_path = value @pyqtProperty(bool) def scale1_label_visible(self): return self.scale1.label_visible @scale1_label_visible.setter def scale1_label_visible(self, new_visible): self.scale1.label_visible = new_visible @pyqtProperty("QString") def scale2_signal_path(self): return self.scale2.signal_path @scale2_signal_path.setter def scale2_signal_path(self, value): self.scale2.signal_path = value @pyqtProperty(bool) def scale2_label_visible(self): return self.scale2.label_visible @scale2_label_visible.setter def scale2_label_visible(self, new_visible): self.scale2.label_visible = new_visible @pyqtProperty(bool) def d_flipped(self): return self.d_vertically_flipped @d_flipped.setter def d_flipped(self, value): self.d_vertically_flipped = value self.scale1.s_flipped = value self.scale2.s_flipped = value @pyqtProperty(float) def lower_red_breakpoint(self): return self.scale1._breakpoints[0] @lower_red_breakpoint.setter def lower_red_breakpoint(self, breakpoint): self.scale1._breakpoints[0] = breakpoint self.scale1.update_configuration() @pyqtProperty(float) def lower_yellow_breakpoint(self): return self.scale1._breakpoints[1] @lower_yellow_breakpoint.setter def lower_yellow_breakpoint(self, breakpoint): self.scale1._breakpoints[1] = breakpoint self.scale1.update_configuration() @pyqtProperty(float) def upper_yellow_breakpoint(self): return self.scale1._breakpoints[2] @upper_yellow_breakpoint.setter def upper_yellow_breakpoint(self, breakpoint): self.scale1._breakpoints[2] = breakpoint self.scale1.update_configuration() @pyqtProperty(float) def upper_red_breakpoint(self): return self.scale1._breakpoints[3] @upper_red_breakpoint.setter def upper_red_breakpoint(self, breakpoint): self.scale1._breakpoints[3] = breakpoint self.scale1.update_configuration() @pyqtProperty(QColor) def lower_red_color(self): return self.scale1._colors[0] @lower_red_color.setter def lower_red_color(self, color): self.scale1._colors[0] = color self.scale1.update_configuration() @pyqtProperty(QColor) def lower_yellow_color(self): return self.scale1._colors[1] @lower_yellow_color.setter def lower_yellow_color(self, color): self.scale1._colors[1] = color self.scale1.update_configuration() @pyqtProperty(QColor) def green_color(self): return self.scale1._colors[2] @green_color.setter def green_color(self, color): self.scale1._colors[2] = color self.scale1.update_configuration() @pyqtProperty(QColor) def upper_yellow_color(self): return self.scale1._colors[3] @upper_yellow_color.setter def upper_yellow_color(self, color): self.scale1._colors[3] = color self.scale1.update_configuration() @pyqtProperty(QColor) def upper_red_color(self): return self.scale1._colors[4] @upper_red_color.setter def upper_red_color(self, color): self.scale1._colors[4] = color self.scale1.update_configuration()
def __init__(self, parent=None): super().__init__() self.cards = {} # type: Dict[GuiCards, QWidget] """ Python's GC will clean up QPropertyAnimations as soon as it leaves the button handler, therefore they will appear not to work. Use members to store the animations. see http://stackoverflow.com/a/6953965 """ self.slide_in_animation = None self.slide_out_animation = None self.animation_group = None self.setObjectName("coffeeFundWindow") """ Store the position and size of visible/hidden cards for the animation sequences """ self.hidden_geometry = None self.visible_geometry = None layout = QStackedLayout() layout.setStackingMode(QStackedLayout.StackAll) card_remove = RemoveCard() self.cards[GuiCards.RemoveCard] = card_remove layout.addWidget(card_remove) card_choose_action = ChooseActionCard() self.cards[GuiCards.ChooseAction] = card_choose_action layout.addWidget(card_choose_action) card_account = AccountCard() self.cards[GuiCards.AccountInfo] = card_account layout.addWidget(card_account) # keep this as last initialized card, the last card will be shown on startup! card_start = StartCard() self.cards[GuiCards.Start] = card_start layout.addWidget(card_start) self.setLayout(layout) self.setWindowTitle("Kaffeekasse") layout.setCurrentWidget(card_start) self.active_card = None card_choose_action.button_account.clicked.connect(self.signal_account) card_choose_action.button_coffee.clicked.connect(self.signal_coffee) card_account.button_back.clicked.connect(self.signal_back)