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 _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 RightPanel(QFrame): def __init__(self, app, parent=None): super().__init__(parent) self._app = app self._pixmap = None self._layout = QVBoxLayout(self) self._stacked_layout = QStackedLayout() self.scrollarea = ScrollArea(self._app, self) self.table_container = self.scrollarea.t # TODO: collection container will be removed self.collection_container = CollectionContainer(self._app, self) self.bottom_panel = BottomPanel(app, self) self._setup_ui() def _setup_ui(self): self.scrollarea.setMinimumHeight(100) self.collection_container.hide() self._layout.addWidget(self.bottom_panel) self._layout.addLayout(self._stacked_layout) self._stacked_layout.addWidget(self.scrollarea) self._stacked_layout.addWidget(self.collection_container) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) def show_model(self, model): self.set_body(self.scrollarea) # TODO: use PreemptiveTask aio.create_task(self.table_container.show_model(model)) def show_songs(self, songs): self.collection_container.hide() self.set_body(self.scrollarea) self.table_container.show_songs(songs) def set_body(self, widget): """ .. versionadded:: 3.7.7 """ if widget is self.table_container: widget = self.scrollarea if widget is not self.scrollarea: self.show_background_image(None) # remove tmp widgets for i in range(self._stacked_layout.count()): w = self._stacked_layout.widget(i) if w not in (self.scrollarea, self.collection_container): self._stacked_layout.removeWidget(w) self._stacked_layout.addWidget(widget) self._stacked_layout.setCurrentWidget(widget) def show_collection(self, coll): def _show_pure_albums_coll(coll): self.set_body(self.scrollarea) reader = wrap(coll.models) self.table_container.show_albums_coll(reader) def _show_pure_songs_coll(coll): self.set_body(self.scrollarea) self.table_container.show_collection(coll) def _show_mixed_coll(coll): self.set_body(self.collection_container) self.collection_container.show_collection(coll) def _show_pure_videos_coll(coll): from feeluown.gui.page_containers.table import VideosRenderer self.set_body(self.scrollarea) reader = wrap(coll.models) renderer = VideosRenderer(reader) aio.create_task(self.table_container.set_renderer(renderer)) if coll.type is CollectionType.sys_library: self._app.browser.goto(page='/colls/library') return types = set() for model in coll.models: types.add(model.meta.model_type) if len(types) >= 2: break if len(types) == 1: type_ = types.pop() if type_ == ModelType.song: _show_pure_songs_coll(coll) elif type_ == ModelType.album: _show_pure_albums_coll(coll) elif type_ == ModelType.video: _show_pure_videos_coll(coll) else: _show_mixed_coll(coll) else: _show_mixed_coll(coll) def show_background_image(self, pixmap): self._pixmap = pixmap if pixmap is None: self.table_container.meta_widget.setMinimumHeight(0) else: height = (self._app.height() - self.bottom_panel.height() - self.table_container.toolbar.height()) // 2 self.table_container.meta_widget.setMinimumHeight(height) self.update() def paintEvent(self, e): """ draw pixmap as a the background with a dark overlay HELP: currently, this cost much CPU """ painter = QPainter(self) painter.setPen(Qt.NoPen) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.SmoothPixmapTransform) # calculate available size draw_width = self.width() draw_height = 10 # spacing defined in table container draw_height += self.bottom_panel.height() if self.table_container.meta_widget.isVisible(): draw_height += self.table_container.meta_widget.height() extra = self.table_container.current_extra if extra is not None and extra.isVisible(): draw_height += extra.height() if self.table_container.toolbar.isVisible(): draw_height += self.table_container.toolbar.height() scrolled = self.scrollarea.verticalScrollBar().value() max_scroll_height = draw_height - self.bottom_panel.height() if scrolled >= max_scroll_height: painter.save() painter.setBrush(self.palette().brush(QPalette.Window)) painter.drawRect(self.bottom_panel.rect()) painter.restore() return if self._pixmap is not None: self._draw_pixmap(painter, draw_width, draw_height, scrolled) self._draw_pixmap_overlay(painter, draw_width, draw_height, scrolled) else: # draw gradient for widgets(bottom panel + meta_widget + ...) above table self._draw_overlay(painter, draw_width, draw_height, scrolled) # if scrolled height > 30, draw background to seperate bottom_panel and body if scrolled >= 30: painter.save() painter.setBrush(self.palette().brush(QPalette.Window)) painter.drawRect(self.bottom_panel.rect()) painter.restore() return # since the body's background color is palette(base), we use # the color to draw background for remain empty area painter.save() painter.setBrush(self.palette().brush(QPalette.Base)) painter.drawRect(0, draw_height, draw_width, self.height() - draw_height) painter.restore() painter.end() def _draw_pixmap_overlay(self, painter, draw_width, draw_height, scrolled): painter.save() rect = QRect(0, 0, draw_width, draw_height) painter.translate(0, -scrolled) gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()) color = self.palette().color(QPalette.Base) if draw_height == self.height(): gradient.setColorAt(0, add_alpha(color, 180)) gradient.setColorAt(1, add_alpha(color, 230)) else: if self._app.theme_mgr.theme == Light: gradient.setColorAt(0, add_alpha(color, 220)) gradient.setColorAt(0.1, add_alpha(color, 180)) gradient.setColorAt(0.2, add_alpha(color, 140)) gradient.setColorAt(0.6, add_alpha(color, 140)) gradient.setColorAt(0.8, add_alpha(color, 200)) gradient.setColorAt(0.9, add_alpha(color, 240)) gradient.setColorAt(1, color) else: gradient.setColorAt(0, add_alpha(color, 50)) gradient.setColorAt(0.6, add_alpha(color, 100)) gradient.setColorAt(0.8, add_alpha(color, 200)) gradient.setColorAt(0.9, add_alpha(color, 240)) gradient.setColorAt(1, color) painter.setBrush(gradient) painter.drawRect(rect) painter.restore() def _draw_overlay(self, painter, draw_width, draw_height, scrolled): painter.save() rect = QRect(0, 0, draw_width, draw_height) painter.translate(0, -scrolled) gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()) gradient.setColorAt(0, self.palette().color(QPalette.Window)) gradient.setColorAt(1, self.palette().color(QPalette.Base)) painter.setBrush(gradient) painter.drawRect(rect) painter.restore() def _draw_pixmap(self, painter, draw_width, draw_height, scrolled): # scale pixmap scaled_pixmap = self._pixmap.scaledToWidth( draw_width, mode=Qt.SmoothTransformation) pixmap_size = scaled_pixmap.size() # draw the center part of the pixmap on available rect painter.save() brush = QBrush(scaled_pixmap) painter.setBrush(brush) # note: in practice, most of the time, we can't show the # whole artist pixmap, as a result, the artist head will be cut, # which causes bad visual effect. So we render the top-center part # of the pixmap here. y = (pixmap_size.height() - draw_height) // 3 painter.translate(0, -y - scrolled) rect = QRect(0, y, draw_width, draw_height) painter.drawRect(rect) painter.restore() def sizeHint(self): size = super().sizeHint() return QSize(760, size.height())
class DialogWindow(QWidget): DIALOG_MAINMENU = 'mainmenu' DIALOG_TALK = 'talk' DIALOG_INPUT = 'input' def __init__(self, soul, win_id): QWidget.__init__(self) self.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setAttribute(Qt.WA_TranslucentBackground) # self.setAttribute(Qt.WA_DeleteOnClose) # self.setMouseTracking(True) # self.setAcceptDrops(True) self.ID = win_id self._soul = soul self._ghost = self._soul.getGhost() self._shellwindow = self._soul.getShellWindow() self._framelessWindowHint = True self.isFlip = False self.setWindowTitle(self._ghost.name) self.setContentsMargins(0, 0, 0, 0) self._bgImage = None self._bgPixmap = None self._bgMask = None self._rect = None self._curPage = 0 self._widgets = {} self._talkLabel = None self._inputLineEdit = None self._callback = None self.init() def init(self): # rect rect = self._soul.memoryRead('DialogRect', []) if len(rect) > 0: self._rect = QRect(rect[0], rect[1], rect[2], rect[3]) self.resize(self._rect.size()) else: p_pos = self._shellwindow.pos() p_size = self._shellwindow.size() self.resize(kikka.const.WindowConst.DialogWindowDefaultSize) x = int(p_pos.x() - self.size().width()) y = int(p_pos.y() + p_size.height() / 2 - self.size().height()) self._rect = QRect(QPoint(x, y), self.size()) rectdata = [ x - p_pos.x(), y - p_pos.y(), self.size().width(), self.size().height() ] self._soul.memoryWrite('DialogRect', rectdata) # default control self._talkLabel = QLabel() self._talkLabel.setAlignment(Qt.AlignLeft | Qt.AlignTop) self._talkLabel.setWordWrap(True) self._inputLabel = QLabel() self._inputLineEdit = QLineEdit() self._inputOk = QPushButton("OK") self._inputOk.clicked.connect(self.onInputOk) self._inputCancel = QPushButton("Cancel") self._inputCancel.clicked.connect(self.onInputCancel) # default UI talkLayout = QVBoxLayout() talkLayout.addWidget(self._talkLabel) talkWidget = QWidget(self) talkWidget.setContentsMargins(0, 0, 0, 0) talkWidget.setLayout(talkLayout) menuWidget = QWidget(self) menuWidget.setContentsMargins(0, 0, 0, 0) l = QHBoxLayout() l.addStretch() l.addWidget(self._inputOk) l.addWidget(self._inputCancel) inputLayout = QVBoxLayout() inputLayout.addWidget(self._inputLabel) inputLayout.addWidget(self._inputLineEdit) inputLayout.addLayout(l) inputLayout.addStretch() inputWidget = QWidget(self) inputWidget.setContentsMargins(0, 0, 0, 0) inputWidget.setLayout(inputLayout) self.setPage(self.DIALOG_MAINMENU, menuWidget) self.setPage(self.DIALOG_TALK, talkWidget) self.setPage(self.DIALOG_INPUT, inputWidget) self._mainLayout = QStackedLayout() self._mainLayout.addWidget(menuWidget) self.setLayout(self._mainLayout) def setFramelessWindowHint(self, boolean): self._framelessWindowHint = boolean if self._framelessWindowHint is False: self.clearMask() self.setWindowFlag(Qt.FramelessWindowHint, False) self.setWindowOpacity(0.8) self.setEnabled(False) self.show() self.move(2 * self.pos().x() - self.geometry().x(), 2 * self.pos().y() - self.geometry().y()) self.update() self.activateWindow() else: self._rect.setX(self.geometry().x() - self._shellwindow.pos().x()) self._rect.setY(self.geometry().y() - self._shellwindow.pos().y()) self._rect.setSize(self.geometry().size()) rectdata = [ self._rect.x(), self._rect.y(), self._rect.width(), self._rect.height() ] self._soul.memoryWrite('DialogRect', rectdata) pos = QPoint(self.pos().x(), self.pos().y()) self.setWindowFlag(Qt.FramelessWindowHint, True) self.setWindowOpacity(1) self.setEnabled(True) self.setMask(self._bgMask) self.show() self.move(pos.x(), pos.y()) def updatePosition(self): if self._framelessWindowHint is False: return p_pos = self._shellwindow.pos() p_size = self._shellwindow.size() new_x = self._rect.x() + p_pos.x() new_y = self._rect.y() + p_pos.y() self.resize(self._rect.size()) flip = False sw, sh = kikka.helper.getScreenResolution() if new_x + self.width() > sw or new_x < 0: flip = True new_x = int(p_pos.x() * 2 + p_size.width() - new_x - self.width()) if new_x + self.width() > sw: new_x = p_pos.x() - self.width() if new_x < 0: new_x = p_pos.x() + p_size.width() if self.isFlip != flip: self.isFlip = flip self.repaint() super().move(new_x, new_y) def setPage(self, tag, qwidget): if tag in self._widgets: self._widgets[tag].deleteLater() qwidget.hide() qwidget.setParent(self) self._widgets[tag] = qwidget def getTalkLabel(self): return self._talkLabel def showInputBox(self, title, default='', callback=None): self._inputLabel.setText(title) self._inputLineEdit.setText(default) self._callback = callback self.show(self.DIALOG_INPUT) def show(self, pageTag=None): if pageTag is None: pageTag = self.DIALOG_MAINMENU elif pageTag not in self._widgets: logging.warning("show: page[%s] not exist" % pageTag) pageTag = self.DIALOG_MAINMENU if self._widgets[pageTag] != self._mainLayout.currentWidget(): self._mainLayout.removeWidget(self._mainLayout.currentWidget()) self._mainLayout.addWidget(self._widgets[pageTag]) self._mainLayout.setCurrentIndex(0) self._curPage = pageTag param = kikka.helper.makeGhostEventParam( self._ghost.ID, self._soul.ID, kikka.const.GhostEvent.Dialog_Show, 'Show') param.data['pageTag'] = self._curPage self._ghost.emitGhostEvent(param) super().show() self.updatePosition() def closeEvent(self, event): self.setFramelessWindowHint(True) event.ignore() pass def resizeEvent(self, event): super().resizeEvent(event) self.repaint() def paintEvent(self, event): painter = QPainter(self) pixmap = QPixmap().fromImage(self._bgImage, Qt.AutoColor) painter.drawPixmap(self.rect(), pixmap) opt = QStyleOption() opt.initFrom(self) self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self) super().paintEvent(event) def setBalloon(self, balloon): self.setMinimumSize(balloon.minimumsize) self.setContentsMargins(balloon.margin[0], balloon.margin[1], balloon.margin[2], balloon.margin[3]) self.setStyleSheet(balloon.stylesheet) self.style().unpolish(self) self.style().polish(self) def repaint(self): self._bgImage = self._ghost.getBalloonImage(self.size(), self.isFlip, self.ID) self._bgPixmap = QPixmap().fromImage(self._bgImage, Qt.AutoColor) self._bgMask = self._bgPixmap.mask() super().repaint() def talkClear(self): self._talkLabel.setText('') def onTalk(self, message, speed=50): text = self._talkLabel.text() text += message self._talkLabel.setText(text) def onInputOk(self): if self._callback is not None: self._callback(self._inputLineEdit.text()) self.hide() def onInputCancel(self): self.hide()
class MainWidget(QMainWindow): __instance = None @staticmethod def getinstance(): if (MainWidget.__instance == None): MainWidget() return MainWidget.__instance def __init__(self, user:User): super().__init__() if (MainWidget.__instance != None): raise Exception ("Singleton") else: self.initUI(user) MainWidget.__instance = self def initUI(self, user:User): self.mainWidget = QWidget() self.setMinimumSize(500,500) self.user = user self.controller = MainWidgetController(self.user) self.setStyleSheet(open('main.css').read()) self.dashboard_button = QPushButton("Dashboard") self.dashboard_button.setFixedWidth(150) self.dashboard_button.clicked.connect(lambda success:self.LoadDashboardLayout(success)) self.dashboard_button.setObjectName("dashboard_button") self.home_button = QPushButton("Home") self.home_button.setFixedWidth(150) self.home_button.clicked.connect(lambda:self.LoadHomeLayout()) self.home_button.setObjectName("home_button") self.profile_button = QPushButton("Profile") self.profile_button.setFixedWidth(150) self.profile_button.clicked.connect(lambda success:self.LoadProfileLayout(success)) self.profile_button.setObjectName("profile_button") self.grid = QGridLayout() self.upperLayout = QHBoxLayout() self.upperLayout.addWidget(self.dashboard_button) self.upperLayout.addWidget(self.home_button) self.upperLayout.addWidget(self.profile_button) self.upperExternal = QFrame() self.upperExternal.setObjectName("upperExternal") self.upperExternal.setLayout(self.upperLayout) #print(self.user.courses) self.home_layout = None self.dashboard_layout = None self.profile_layout = None self.course_layout = None self.new_course_layout = None self.movie_layout = None self.addmovie_layout = None self.CourseMovies_layout = None self.changepass_layout = None self.stack = QStackedLayout() self.grid.addWidget(self.upperExternal,1,1) self.grid.addLayout(self.stack,2,1) self.mainWidget.setLayout(self.grid) self.setCentralWidget(self.mainWidget) self.LoadHomeLayout() # self.Recommender=RecommendationEngine() # self.Recommender.LoadRecommendations(self.user) exit = QAction("&Exit", self) exit.triggered.connect(self.closeEvent) self.show() def closeEvent(self, event): self.silence() close = QMessageBox() close.setText("You sure?") close.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel) close = close.exec() if close == QMessageBox.Yes: event.accept() else: event.ignore() #HomeLayoout---------------------------------------------------------------------------------- #Sets homelayout as default layout def LoadHomeLayout(self): self.setWindowTitle("Home") if self.home_layout == None: self.home_layout = HomeLayout(self.user) self.home_layout._WatchMovie_.connect(lambda url, M_ID:self.LoadMovieLayout(url, M_ID)) self.stack.addWidget(self.home_layout) self.stack.setCurrentWidget(self.home_layout) self.silence() #sets movielayout as default layout def LoadMovieLayout(self, url, movieID): self.setWindowTitle("Movie") if self.movie_layout!=None: self.stack.removeWidget(self.movie_layout) del self.movie_layout self.movie_layout = MovieLayout(url, movieID, self.user) self.stack.addWidget(self.movie_layout) self.stack.setCurrentWidget(self.movie_layout) #DashBoardLayout---------------------------------------------------------------------------------- #sets dashboard layout as default layout def LoadDashboardLayout(self, success): if self.dashboard_layout!=None: self.stack.removeWidget(self.dashboard_layout) del self.dashboard_layout self.setWindowTitle("Dashboard") self.dashboard_layout = DashboardLayout(self.user) self.dashboard_layout.new_course_request.connect(self.LoadCourseLayout) self.dashboard_layout.openCourse_request.connect(lambda x: self.LoadCourseMovies(x)) self.stack.addWidget(self.dashboard_layout) self.stack.setCurrentWidget(self.dashboard_layout) self.silence() if(success == 1): self.dashboard_layout.message.setText("Successfully Submitted Course") self.course_layout = None elif(success == 2): self.dashboard_layout.message.setText("Successfully Submitted Movie") self.addmovie_layout = None elif(success == 3): pass elif(success == 4): self.dashboard_layout.message.setText("Successfully Enrolled in Course") self.course_layout = None #sets course layout as default layout (upload courses) def LoadCourseLayout(self): self.setWindowTitle("Add Course") if self.course_layout == None and isinstance(self.user, Professor) == True: self.course_layout = CourseInputDialog(self.user) self.course_layout.loaddashlayout.connect(lambda success:self.LoadDashboardLayout(success)) self.stack.addWidget(self.course_layout) elif self.course_layout == None and isinstance(self.user, Student) == True: self.course_layout = CourseInputDialog(self.user) self.course_layout.loaddashlayout.connect(lambda success:self.LoadDashboardLayout(success)) self.stack.addWidget(self.course_layout) # self.course_layout.refreshDash.connect(self.) self.course_layout.refreshCourses_request.connect(self.RefreshProfile) self.stack.setCurrentWidget(self.course_layout) #sets dash movie layout as default layout (upload movie) def LoadDashMovieLayout(self, courseID): self.setWindowTitle("Add Movie") if self.addmovie_layout!=None: self.stack.removeWidget(self.addmovie_layout) del self.addmovie_layout self.addmovie_layout = MovieInputDialog(self.user, courseID) self.addmovie_layout.goback_request.connect(lambda C_ID:self.LoadCourseMovies(C_ID)) self.stack.addWidget(self.addmovie_layout) self.stack.setCurrentWidget(self.addmovie_layout) def LoadCourseMovies(self, courseID): self.setWindowTitle("Course Movies") if self.CourseMovies_layout!=None: self.stack.removeWidget(self.CourseMovies_layout) del self.CourseMovies_layout self.CourseMovies_layout = CourseMovieLayout(self.user, courseID) self.CourseMovies_layout.new_movie_request.connect(lambda C_ID: self.LoadDashMovieLayout(C_ID)) self.CourseMovies_layout.goback_request.connect(lambda success:self.LoadDashboardLayout(success)) self.CourseMovies_layout._WatchMovie_.connect(lambda url, M_ID:self.LoadMovieLayout(url, M_ID)) self.stack.addWidget(self.CourseMovies_layout) self.stack.setCurrentWidget(self.CourseMovies_layout) #ProfileLayout--------------------------------------------------------------------------------------------- #sets profile layout as default layout def LoadProfileLayout(self, success): self.setWindowTitle("Profile") if self.profile_layout != None: self.stack.removeWidget(self.profile_layout) del self.profile_layout self.profile_layout = ProfileLayout(self.user) self.profile_layout.changePass_request.connect(lambda : self.LoadChangePassLayout()) self.profile_layout.changeImage_request.connect(lambda image: self.ChangeImage(image)) if(success == 1): self.profile_layout.errorMessage.setText("Password Changed Successfully") self.stack.addWidget(self.profile_layout) self.stack.setCurrentWidget(self.profile_layout) self.silence() def LoadChangePassLayout(self): self.setWindowTitle("Change Password") if self.changepass_layout == None: self.changepass_layout = ChangePasswordLayout(self.user) self.changepass_layout.goback_request.connect(lambda success:self.LoadProfileLayout(success)) self.stack.addWidget(self.changepass_layout) self.stack.setCurrentWidget(self.changepass_layout) #----------------------------------------------------------------------------------------------------------- #stops movie from running in background (movie cleanup) def silence(self): if(self.movie_layout != None): self.movie_layout.Stop() def RefreshProfile(self): self.user.courses = self.controller.refresh() def ChangeImage(self, image): self.user.image = image
class mainWindow(QMainWindow): end_game = False def __init__(self): super().__init__() self.setWindowTitle('Oczko 21') self.setGeometry(400, 40, 700, 640) self.create_welcome_layout() self.stacked_layout = QStackedLayout() self.stacked_layout.addWidget(self.welcome_widget) self.central_widget = QWidget() self.central_widget.setLayout(self.stacked_layout) self.setCentralWidget(self.central_widget) #====================Create New Game Layout===================== self.create_new_game_layout() self.stacked_layout.addWidget(self.new_game_widget) #==========================MAIN MENU==================================== self.statusBar() newGame = QAction('&New Game', self) newGame.setStatusTip('Starts a new game...') newGame.triggered.connect(self.newGame_opt) help = QAction('&Help', self) help.setStatusTip('Help...') help.triggered.connect(self.help_opt) quitGame = QAction('&Quit', self) quitGame.setStatusTip('Quits the game...') quitGame.triggered.connect(self.quit_opt) mainMenu = self.menuBar() optionsMenu = mainMenu.addMenu('&Options') optionsMenu.addAction(newGame) optionsMenu.addAction(help) optionsMenu.addAction(quitGame) #=======================END MAIN MENU=========================================== def newGame_opt(self): #options from menu bar if self.stacked_layout.currentIndex() != 0: choice = QMessageBox.question(self, 'Start a new game', 'Do you want to start a new game?', QMessageBox.Yes | QMessageBox.No) if choice == QMessageBox.Yes: self.new_game_radio_button.check_first() self.stacked_layout.setCurrentIndex(1) self.player1_line_edit.setText('Player 1') self.player2_line_edit.setText('Player 2') else: pass else: self.new_game_radio_button.check_first() self.stacked_layout.setCurrentIndex(1) self.player1_line_edit.setText('Player 1') self.player2_line_edit.setText('Player 2') def quit_opt(self): #options from menu bar choice = QMessageBox.question(self, 'Exit', 'Do you really want to exit the game?', QMessageBox.Yes | QMessageBox.No) if choice == QMessageBox.Yes: sys.exit() else: pass def help_opt(self): # options from menu bar self.dialog = HelpWindow() self.dialog.show() @classmethod def end_game_change_value(cls, value): #method used to verify if game has ended cls.end_game = value def create_welcome_layout(self): #first layout self.welcome_layout = QVBoxLayout() self.welcome_widget = QWidget() self.welcome_widget.setLayout(self.welcome_layout) def create_new_game_layout(self): #start new game layout (new game menu) self.player1_label = QLabel('First player name:') self.player2_label = QLabel('Second player name:') self.player1_line_edit = QLineEdit() self.player2_line_edit = QLineEdit() self.cancel_button = QPushButton('Cancel') self.cancel_button.setMaximumWidth(330) self.cancel_button.setMinimumWidth(330) self.cancel_button.setMinimumHeight(60) self.start_button = QPushButton('Start New Game') self.start_button.setMaximumWidth(330) self.start_button.setMinimumWidth(330) self.start_button.setMinimumHeight(60) self.start_button.clicked.connect(self.start_new_game) self.cancel_button.clicked.connect(self.cancel) self.player_grid = QGridLayout() self.new_game_grid = QGridLayout() #player grid self.player_grid.addWidget(self.player1_label, 0, 0) self.player_grid.addWidget(self.player2_label, 1, 0) self.player_grid.addWidget(self.player1_line_edit, 0, 1) self.player_grid.addWidget(self.player2_line_edit, 1, 1) #new game grid self.new_game_radio_button = RadioButton('Play with', ('NPC', 'Friend')) self.new_game_grid.addWidget(self.new_game_radio_button, 0, 0) self.new_game_grid.addLayout(self.player_grid, 0, 1) self.new_game_grid.addWidget(self.cancel_button, 1, 0) self.new_game_grid.addWidget(self.start_button, 1, 1) self.new_game_widget = QWidget() self.new_game_widget.setLayout(self.new_game_grid) def create_game_layout(self, player_type): self.player1_points = QLabel('0') self.player1_points.setAlignment(Qt.AlignTop) self.player2_points = QLabel('0') self.player2_points.setAlignment(Qt.AlignTop) self.player1_name = QLabel(self.player1_line_edit.text()) if player_type == 1: self.player2_name = QLabel(self.player2_line_edit.text() + ' (NPC)') else: self.player2_name = QLabel(self.player2_line_edit.text()) self.points1_label = QLabel('Points:') self.points1_label.setAlignment(Qt.AlignBottom) self.points2_label = QLabel('Points:') self.points2_label.setAlignment(Qt.AlignBottom) self.player1_card = QLabel() self.player2_card = QLabel() self.stop_button_player1 = QPushButton('Stop') self.pull_button_player1 = QPushButton('Pull') self.stop_button_player2 = QPushButton('Stop') self.pull_button_player2 = QPushButton('Pull') self.new_deal_button = QPushButton('New Deal') self.information_field = QPlainTextEdit('Log here baby') self.information_field.setMaximumHeight(243) self.information_field.setMaximumWidth(200) #Buttons connection self.stop_button_player1.clicked.connect( lambda: self.stop_card_player1(player_type)) self.stop_button_player1.setMinimumHeight(30) self.pull_button_player1.clicked.connect( lambda: self.pull_card_player1(player_type)) self.pull_button_player1.setMinimumHeight(30) self.stop_button_player2.clicked.connect(self.stop_card_player2) self.stop_button_player2.setMinimumHeight(30) self.pull_button_player2.clicked.connect(self.pull_card_player2) self.pull_button_player2.setMinimumHeight(30) self.new_deal_button.clicked.connect(self.new_deal) self.new_deal_button.setMaximumWidth(90) self.new_deal_button.setMinimumHeight(80) #Table self.table = QTableWidget() self.table.setRowCount(11) self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels( ("{0};{1};").format(self.player1_name.text(), self.player2_name.text()).split(";")) self.table.setVerticalHeaderLabels( ("1;2;3;4;5;6;7;8;9;10;SUM").split(";")) self.table.setMaximumHeight(355) self.table.setMaximumWidth(237) #Grids definitions self.main_game_grid = QGridLayout() self.board_grid = QGridLayout() self.table_grid = QGridLayout() self.below_table_grid = QGridLayout() self.player1_grid = QGridLayout() self.player2_grid = QGridLayout() self.player1_board_grid = QGridLayout() self.player2_board_grid = QGridLayout() self.player1_buttons_grid = QGridLayout() self.player2_buttons_grid = QGridLayout() self.player1_points_grid = QGridLayout() self.player2_points_grid = QGridLayout() #player points grids self.player1_points_grid.addWidget(self.points1_label, 0, 0) self.player1_points_grid.addWidget(self.player1_points, 1, 0) self.player2_points_grid.addWidget(self.points2_label, 0, 0) self.player2_points_grid.addWidget(self.player2_points, 1, 0) #player buttons grids self.player1_buttons_grid.addWidget(self.stop_button_player1, 0, 0) self.player1_buttons_grid.addWidget(self.pull_button_player1, 0, 1) self.player2_buttons_grid.addWidget(self.stop_button_player2, 0, 0) self.player2_buttons_grid.addWidget(self.pull_button_player2, 0, 1) #player board grids self.player1_board_grid.addWidget(self.player1_name, 0, 0) self.player1_board_grid.addWidget(self.player1_card, 0, 1) self.player1_board_grid.addLayout(self.player1_points_grid, 0, 3) self.player2_board_grid.addWidget(self.player2_name, 0, 0) self.player2_board_grid.addWidget(self.player2_card, 0, 1) self.player2_board_grid.addLayout(self.player2_points_grid, 0, 3) #player grids self.player1_grid.addLayout(self.player1_buttons_grid, 0, 0) self.player1_grid.addLayout(self.player1_board_grid, 1, 0) self.player2_grid.addLayout(self.player2_buttons_grid, 1, 0) self.player2_grid.addLayout(self.player2_board_grid, 0, 0) #below table grid self.below_table_grid.addWidget(self.information_field, 0, 0) self.below_table_grid.addWidget(self.new_deal_button, 0, 1) #three main grids self.board_grid.addLayout(self.player1_grid, 0, 0) self.board_grid.addLayout(self.player2_grid, 1, 0) self.table_grid.addWidget(self.table, 0, 0) self.table_grid.addLayout(self.below_table_grid, 1, 0) self.main_game_grid.addLayout(self.board_grid, 0, 0) self.main_game_grid.addLayout(self.table_grid, 0, 1) # layout self.game_widget = QWidget() self.game_widget.setLayout(self.main_game_grid) def cancel(self): self.stacked_layout.setCurrentIndex(0) def start_new_game(self): player_type = self.new_game_radio_button.selected_button() if len(self.player1_line_edit.text()) > 10 or len( self.player2_line_edit.text()) > 10: QMessageBox.information( self, "Too long name", "At least one of player's name is too long. It has to be shorter than 10 characters." ) elif self.player1_line_edit.text( ) == '' or self.player2_line_edit.text() == '': QMessageBox.information( self, "Empty name", "At least one of player's name is empty. Please provide correct one." ) else: if self.stacked_layout.count() > 2: self.stacked_layout.removeWidget(self.game_widget) self.create_game_layout(player_type) self.stacked_layout.addWidget(self.game_widget) self.stacked_layout.setCurrentIndex(2) self.player1_score = 0 self.player2_score = 0 self.match = -1 self.new_match() def new_match(self): self.end_game_change_value(False) self.new_deal_button.setDisabled(True) self.match += 1 self.deck = Deck() self.turn = 0 self.disable_player2_buttons() self.stop_counter = 0 self.player1_allcards = [] self.player2_allcards = [] self.pixmap = QPixmap('karty\empty.png') self.pixmap = self.pixmap.scaledToWidth(180) self.player1_card.setPixmap(self.pixmap) self.player2_card.setPixmap(self.pixmap) self.information_field.setPlainText('New deal! {0} starts'.format( self.player1_name.text())) def pull_card_player1(self, player_type): #card pixmap self.pixmap1 = QPixmap( os.path.join('karty', '{0}.png').format(self.deck.pack[self.turn])) self.pixmap1 = self.pixmap1.scaledToWidth(180) self.player1_card.setPixmap(self.pixmap1) self.player1_points.setText( str( int(self.player1_points.text()) + self.points(self.deck.pack[self.turn][:2]))) #log info self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} pulls and gains {1} points'.format( self.player1_name.text(), str(self.points(self.deck.pack[self.turn][:2])))) self.player1_allcards.append(self.deck.pack[self.turn]) self.turn += 1 self.stop_counter = 0 self.disable_player1_buttons() if player_type == 1: self.game_function() if self.end_game == False: self.npc_turn() elif player_type == 2 and self.end_game == False: self.enable_player2_buttons() self.game_function() else: self.disable_player1_buttons() self.disable_player2_buttons() def stop_card_player1(self, player_type): self.stop_counter += 1 #log info self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} stops the card'.format(self.player1_name.text())) self.disable_player1_buttons() if player_type == 1: self.game_function() if self.end_game == False: self.npc_turn() elif player_type == 2 and self.end_game == False: self.enable_player2_buttons() self.game_function() else: self.disable_player1_buttons() self.disable_player2_buttons() def pull_card_player2(self): #card pixmap self.pixmap2 = QPixmap( os.path.join('karty', '{0}.png').format(self.deck.pack[self.turn])) self.pixmap2 = self.pixmap2.scaledToWidth(180) self.player2_card.setPixmap(self.pixmap2) self.player2_points.setText( str( int(self.player2_points.text()) + self.points(self.deck.pack[self.turn][:2]))) #log info self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} pulls and gains {1} points'.format( self.player2_name.text(), str(self.points(self.deck.pack[self.turn][:2])))) self.player2_allcards.append(self.deck.pack[self.turn]) self.turn += 1 self.stop_counter = 0 self.disable_player2_buttons() if self.end_game == False: self.enable_player1_buttons() self.game_function() else: self.disable_player1_buttons() def stop_card_player2(self): self.disable_player2_buttons() self.stop_counter += 1 #log info self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} stops the card'.format(self.player2_name.text())) if self.end_game == False: self.enable_player1_buttons() self.game_function() def game_function(self): #check whether there is a winning result if int(self.player1_points.text()) == 21 and int( self.player2_points.text()) == 21: self.draw() if int(self.player1_points.text()) == 21 and self.stop_counter == 1: self.player1_wins() if int(self.player2_points.text()) == 21 and self.stop_counter == 1: self.player2_wins() # =====================Two Aces======================== if int(self.player1_points.text() ) == 22 and 'AA' in self.player1_allcards[ 0] and 'AA' in self.player1_allcards[1]: self.player1_wins() self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} has two Aces!'.format(self.player1_name.text())) if int(self.player2_points.text() ) == 22 and 'AA' in self.player2_allcards[ 0] and 'AA' in self.player2_allcards[1]: self.player2_wins() self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} has two Aces!'.format(self.player1_name.text())) # ================================================================== #============================Two times Stop button in row============================ if self.stop_counter == 2: if int(self.player1_points.text()) > int( self.player2_points.text()): self.player1_wins() elif int(self.player1_points.text()) < int( self.player2_points.text()): self.player2_wins() else: self.draw() if int(self.player1_points.text()) > 21: # player 1 exceeds 21 points self.information_field.setPlainText( self.information_field.toPlainText() + '. 21 is exceeded!') self.player2_wins() if int(self.player2_points.text()) > 21: # player 2 exceeds 21 points self.disable_player1_buttons() self.information_field.setPlainText( self.information_field.toPlainText() + '. 21 is exceeded!') self.player1_wins() def npc_turn(self): #determines when npc pulls or stops the card time.sleep(0.5) if int(self.player1_points.text()) == 21 and int( self.player2_points.text()) in [18, 19]: self.pull_card_player2() elif int(self.player1_points.text()) == 21 and int( self.player2_points.text()) == 20: self.stop_card_player2() elif int(self.player1_points.text()) >= 21: self.stop_card_player2() elif int(self.player1_points.text()) >= int( self.player2_points.text()) or int( self.player2_points.text()) <= 11: self.pull_card_player2() elif int(self.player2_points.text()) == 12: if random.randint(0, 100) < 85: self.pull_card_player2() else: self.stop_card_player2() elif int(self.player2_points.text()) == 13: if random.randint(0, 100) < 80: self.pull_card_player2() else: self.stop_card_player2() elif int(self.player2_points.text()) == 14: if random.randint(0, 100) < 70: self.pull_card_player2() else: self.stop_card_player2() elif int(self.player2_points.text()) == 15: if random.randint(0, 100) < 50: self.pull_card_player2() else: self.stop_card_player2() elif int(self.player2_points.text()) == 16: if random.randint(0, 100) < 35: self.pull_card_player2() else: self.stop_card_player2() elif int(self.player2_points.text()) == 17: if random.randint(0, 100) < 20: self.pull_card_player2() else: self.stop_card_player2() elif int(self.player2_points.text()) >= 18: if random.randint(0, 100) < 5: self.pull_card_player2() else: self.stop_card_player2() else: self.stop_card_player2() def player1_wins(self): #action when player 1 wins self.player1_score += 1 self.sum_rows() self.disable_player1_buttons() self.disable_player2_buttons() self.table.setItem(self.match, 0, QTableWidgetItem('1')) self.table.setItem(self.match, 1, QTableWidgetItem('0')) self.end_game_change_value(True) #log self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} wins the deal with {1} points!'.format( self.player1_name.text(), self.player1_points.text())) if self.match < 9: self.new_deal_button.setDisabled(False) else: self.result_message(self.player1_score, self.player2_score) def player2_wins(self): #action when player 2 wins self.player2_score += 1 self.sum_rows() self.disable_player1_buttons() self.disable_player2_buttons() self.table.setItem(self.match, 0, QTableWidgetItem('0')) self.table.setItem(self.match, 1, QTableWidgetItem('1')) self.end_game_change_value(True) #log self.information_field.setPlainText( self.information_field.toPlainText() + '\n{0} wins the deal with {1} points!'.format( self.player2_name.text(), self.player2_points.text())) if self.match < 9: self.new_deal_button.setDisabled(False) else: self.result_message(self.player1_score, self.player2_score) def draw(self): #action when there is a draw self.disable_player1_buttons() self.disable_player2_buttons() self.table.setItem(self.match, 0, QTableWidgetItem('0')) self.table.setItem(self.match, 1, QTableWidgetItem('0')) self.end_game_change_value(True) #log self.information_field.setPlainText( self.information_field.toPlainText() + '\nDraw!') if self.match < 9: self.new_deal_button.setDisabled(False) else: self.result_message(self.player1_score, self.player2_score) def result_message(self, player1_score, player2_score): if player1_score > player2_score: QMessageBox.information( self, "{0} won!".format(self.player1_name.text()), "The score is {0}:{1}. Good luck next time {2}!".format( player1_score, player2_score, self.player2_name.text())) elif player1_score < player2_score: QMessageBox.information( self, "{0} won!".format(self.player2_name.text()), "The score is {0}:{1}. Good luck next time {2}!".format( player2_score, player1_score, self.player1_name.text())) else: QMessageBox.information( self, "Draw!", "Both players scored {0} points".format(player1_score)) def disable_player1_buttons(self): self.pull_button_player1.setDisabled(True) self.stop_button_player1.setDisabled(True) def enable_player1_buttons(self): self.pull_button_player1.setDisabled(False) self.stop_button_player1.setDisabled(False) def disable_player2_buttons(self): self.pull_button_player2.setDisabled(True) self.stop_button_player2.setDisabled(True) def enable_player2_buttons(self): self.pull_button_player2.setDisabled(False) self.stop_button_player2.setDisabled(False) def points(self, value): #method to match card's name with its points value score = { '11': 1, '22': 2, '33': 3, '44': 4, '55': 5, '66': 6, '77': 7, '88': 8, '99': 9, '10': 10, 'WW': 2, 'DD': 3, 'KK': 4, 'AA': 11 } return score[value] def sum_rows(self): #sums rows from the table self.table.setItem(10, 0, QTableWidgetItem(str(self.player1_score))) self.table.setItem(10, 1, QTableWidgetItem(str(self.player2_score))) def new_deal(self): #start new deal self.enable_player1_buttons() self.player1_card.setText('') self.player2_card.setText('') self.player1_points.setText('0') self.player2_points.setText('0') self.new_match()
class MainUI(QWidget): def __init__(self, parent=None): # 创建更新历史数据的线程 self.hist_data_thread = UpdateHistData() self.hist_data_thread.update_hist_data_signal.connect( self.update_hist_data) self.hist_data_thread.start() # 创建实时价格更新线程 self.live_price_thread = GetLivePrice() self.live_price_thread.update_data.connect(self.update_price) # 在历史数据更新完成后再启动 super(MainUI, self).__init__(parent) # 设置窗口名称 self.setWindowTitle("APIA Quant") # initial size self.resize(1200, 600) # 完成一些复杂的主要的布局 self.init_ui() # 窗口居中显示 self.center() # 设置窗口透明度 self.setWindowOpacity(0.98) self.main_layout.setSpacing(0) #设置窗口主题 self.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) def init_ui(self): # 创建主部件的网格布局 self.main_layout = QHBoxLayout(self) # 左侧布局开始 # 创建左侧frame self.left_frame = QFrame(self) self.left_frame.setFrameShape(QFrame.StyledPanel) #在这个frame中使用垂直布局 self.left_verticalLayout = QVBoxLayout(self.left_frame) # function buttons self.login_btn = QPushButton(self.left_frame) self.login_btn.setText("Login") self.login_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.login_btn.clicked.connect(self.login) self.login_btn.setEnabled(False) self.login_btn.setShortcut(Qt.Key_Return) self.home_btn = QPushButton(self.left_frame) self.home_btn.setText('Home') self.home_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.home_btn.clicked.connect(lambda: self.display_right(index=1)) self.home_btn.setEnabled(False) self.manage_etf_btn = QPushButton(self.left_frame) self.manage_etf_btn.setText('Manage ETFs') self.manage_etf_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.manage_etf_btn.clicked.connect( lambda: self.display_right(index=2)) self.manage_etf_btn.setEnabled(False) self.get_hist_btn = QPushButton(self.left_frame) self.get_hist_btn.setText('Update Historical Data') self.get_hist_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.get_hist_btn.clicked.connect(lambda: self.display_right(index=3)) self.get_hist_btn.setEnabled(False) self.candle_btn = QPushButton(self.left_frame) self.candle_btn.setText('Show Candles') self.candle_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.candle_btn.clicked.connect(lambda: self.display_right(index=4)) self.candle_btn.setEnabled(False) self.trading_signal_btn = QPushButton(self.left_frame) self.trading_signal_btn.setText('Trading Signals') self.trading_signal_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.trading_signal_btn.clicked.connect( lambda: self.display_right(index=5)) self.trading_signal_btn.setEnabled(False) self.back_test_btn = QPushButton(self.left_frame) self.back_test_btn.setText('Back Test') self.back_test_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.back_test_btn.clicked.connect(lambda: self.display_right(index=6)) self.back_test_btn.setEnabled(False) self.core_strategy_btn = QPushButton(self.left_frame) self.core_strategy_btn.setText('Core Strategy Table') self.core_strategy_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.core_strategy_btn.clicked.connect( lambda: self.display_right(index=7)) self.core_strategy_btn.setEnabled(False) self.position_calculator_btn = QPushButton(self.left_frame) self.position_calculator_btn.setText('Position Calculator') self.position_calculator_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.position_calculator_btn.clicked.connect( lambda: self.display_right(index=8)) self.position_calculator_btn.setEnabled(False) self.quit_btn = QPushButton(self.left_frame) self.quit_btn.setText('Quit') self.quit_btn.setFont(QFont('Arial', 12, QFont.Bold)) self.quit_btn.clicked.connect(QCoreApplication.instance().quit) self.quit_btn.setEnabled(True) # 将上述功能按键添加到当前的垂直布局 self.left_verticalLayout.addWidget(self.login_btn) self.left_verticalLayout.addWidget(self.home_btn) self.left_verticalLayout.addWidget(self.manage_etf_btn) self.left_verticalLayout.addWidget(self.get_hist_btn) self.left_verticalLayout.addWidget(self.candle_btn) self.left_verticalLayout.addWidget(self.trading_signal_btn) self.left_verticalLayout.addWidget(self.back_test_btn) self.left_verticalLayout.addWidget(self.core_strategy_btn) self.left_verticalLayout.addWidget(self.position_calculator_btn) self.left_verticalLayout.addWidget(self.quit_btn) # 右侧布局开始 # 创建右侧frame self.right_frame = QFrame(self) self.right_frame.setFrameShape(QFrame.StyledPanel) #这里之后会另外进行UI创建的 self.login_pg = Login() self.get_hist_pg = GetHistData() # 创建别的页面之前先更新数据 self.get_hist_pg.get_hist_data() self.home_pg = Home() self.candle_pg = Candle() self.manage_etf_pg = ETFManagement() self.trading_signal_pg = TradingSignal() self.back_test_pg = BackTest() self.core_strategy_pg = CoreStrategy() self.position_calculator_pg = PositionCalculator() # 在右侧frame创建stack self.stack = QStackedLayout(self.right_frame) #将上面的页面加入到stack self.stack.addWidget(self.login_pg) self.stack.addWidget(self.home_pg) self.stack.addWidget(self.manage_etf_pg) self.stack.addWidget(self.get_hist_pg) self.stack.addWidget(self.candle_pg) self.stack.addWidget(self.trading_signal_pg) self.stack.addWidget(self.back_test_pg) self.stack.addWidget(self.core_strategy_pg) self.stack.addWidget(self.position_calculator_pg) # 用于更新etf列表的信号连接 self.manage_etf_pg.re_init_signal.connect(self.re_init) # 创建splitter self.splitter = QSplitter(Qt.Horizontal) self.splitter.addWidget(self.left_frame) self.splitter.addWidget(self.right_frame) self.splitter.setSizes((200, 800)) # 将splitter加入到main_layout self.main_layout.addWidget(self.splitter) self.setLayout(self.main_layout) # 窗口最大化 # self.showMaximized() def center(self): # 获取桌面尺寸 screen = QDesktopWidget().screenGeometry() # 获取窗口本身的尺寸和位置 size = self.geometry() # 对窗口进行平移 self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def display_right(self, index): # 在右边frame显示对应的页面 self.stack.setCurrentIndex(index) if index != 2: self.get_hist_pg.pgb.setVisible(False) self.get_hist_pg.pgb.setValue(0) def login(self): if LoginForm().exec_() == QDialog.Accepted: # 将login按钮设置为不可用 self.login_btn.setText("Welcome to APIA Quant System") self.login_btn.setEnabled(False) # 将剩下的按钮全部设为可用,代表登录成功 self.home_btn.setEnabled(True) self.manage_etf_btn.setEnabled(True) self.get_hist_btn.setEnabled(True) self.candle_btn.setEnabled(True) self.trading_signal_btn.setEnabled(True) self.back_test_btn.setEnabled(True) self.core_strategy_btn.setEnabled(True) self.position_calculator_btn.setEnabled(True) # 直接跳转至home页面 self.stack.setCurrentIndex(1) def re_init(self): # 先终止线程,防止数据对不上 self.live_price_thread.terminate() self.live_price_thread.etfs = np.load('./Data/etfs.npy').tolist() # 重新启动线程 self.live_price_thread.start() self.stack.removeWidget(self.home_pg) del self.home_pg self.stack.removeWidget(self.manage_etf_pg) del self.manage_etf_pg self.stack.removeWidget(self.get_hist_pg) del self.get_hist_pg self.stack.removeWidget(self.candle_pg) del self.candle_pg self.stack.removeWidget(self.trading_signal_pg) del self.trading_signal_pg self.stack.removeWidget(self.back_test_pg) del self.back_test_pg self.stack.removeWidget(self.core_strategy_pg) del self.core_strategy_pg self.stack.removeWidget(self.position_calculator_pg) del self.position_calculator_pg # 创建别的页面之前先更新数据 # self.get_hist_pg.get_hist_data() self.home_pg = Home() self.manage_etf_pg = ETFManagement() self.get_hist_pg = GetHistData() self.candle_pg = Candle() self.trading_signal_pg = TradingSignal() self.back_test_pg = BackTest() self.core_strategy_pg = CoreStrategy() self.position_calculator_pg = PositionCalculator() # 将上面的页面加入到stack self.stack.addWidget(self.login_pg) self.stack.addWidget(self.home_pg) self.stack.addWidget(self.manage_etf_pg) self.stack.addWidget(self.get_hist_pg) self.stack.addWidget(self.candle_pg) self.stack.addWidget(self.trading_signal_pg) self.stack.addWidget(self.back_test_pg) self.stack.addWidget(self.core_strategy_pg) self.stack.addWidget(self.position_calculator_pg) self.manage_etf_pg.re_init_signal.connect(window.re_init) self.stack.setCurrentIndex(1) def update_hist_data(self, sig): print(sig) self.hist_data_thread.terminate() self.live_price_thread.start() self.login_btn.setEnabled(True) def update_price(self, data): self.home_pg.show_live_price(data) self.candle_pg.update_price(data) self.position_calculator_pg.update_position_table(data)
class MainWidget(QMainWindow): def __init__(self, user: User): super().__init__() self.mainWidget = QWidget() self.setMinimumSize(500, 500) self.user = user self.setStyleSheet(open('main.css').read()) self.dashboard_button = QPushButton("Dashboard") self.dashboard_button.clicked.connect( lambda success: self.LoadDashboardLayout(success)) self.home_button = QPushButton("Home") self.home_button.clicked.connect(lambda: self.LoadHomeLayout()) self.profile_button = QPushButton("Profile") self.profile_button.clicked.connect( lambda success: self.LoadProfileLayout(success)) self.grid = QGridLayout() self.upperLayout = QHBoxLayout() self.upperLayout.addWidget(self.dashboard_button) self.upperLayout.addWidget(self.home_button) self.upperLayout.addWidget(self.profile_button) self.upperExternal = QFrame() self.upperExternal.setStyleSheet( ".QFrame{background-color: white; border: 2px solid black; border-radius: 10px;}" ) self.upperExternal.setLayout(self.upperLayout) #print(self.user.courses) self.home_layout = None self.dashboard_layout = None self.profile_layout = None self.course_layout = None self.new_course_layout = None self.movie_layout = None self.addmovie_layout = None self.CourseMovies_layout = None self.changepass_layout = None self.stack = QStackedLayout() self.grid.addWidget(self.upperExternal, 1, 1) self.grid.addLayout(self.stack, 2, 1) self.mainWidget.setLayout(self.grid) self.setCentralWidget(self.mainWidget) self.LoadHomeLayout() # self.Recommender=RecommendationEngine() # self.Recommender.LoadRecommendations(self.user) exit = QAction("&Exit", self) exit.triggered.connect(self.closeEvent) self.show() def closeEvent(self, event): self.silence() close = QMessageBox() close.setText("You sure?") close.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel) close = close.exec() if close == QMessageBox.Yes: event.accept() else: event.ignore() #HomeLayoout---------------------------------------------------------------------------------- #Sets homelayout as default layout def LoadHomeLayout(self): self.setWindowTitle("Home") if self.home_layout == None: self.home_layout = HomeLayout(self.user) self.home_layout._WatchMovie_.connect( lambda url, M_ID: self.LoadMovieLayout(url, M_ID)) self.stack.addWidget(self.home_layout) self.stack.setCurrentWidget(self.home_layout) #sets movielayout as default layout def LoadMovieLayout(self, url, movieID): self.setWindowTitle("Movie") if self.movie_layout != None: self.stack.removeWidget(self.movie_layout) del self.movie_layout self.movie_layout = MovieLayout(url, movieID, self.user) self.stack.addWidget(self.movie_layout) self.stack.setCurrentWidget(self.movie_layout) #DashBoardLayout---------------------------------------------------------------------------------- #sets dashboard layout as default layout def LoadDashboardLayout(self, success): if (success == 1): self.dashboard_layout.message.setText( "Successfully Submitted Course") self.course_layout = None elif (success == 2): self.dashboard_layout.message.setText( "Successfully Submitted Movie") self.addmovie_layout = None elif (success == 3): pass self.setWindowTitle("Dashboard") if self.dashboard_layout == None: self.dashboard_layout = DashboardLayout(self.user) self.dashboard_layout.new_course_request.connect( self.LoadCourseLayout) self.dashboard_layout.openCourse_request.connect( lambda x: self.LoadCourseMovies(x)) self.stack.addWidget(self.dashboard_layout) self.stack.setCurrentWidget(self.dashboard_layout) self.silence() #sets course layout as default layout (upload courses) def LoadCourseLayout(self): self.setWindowTitle("Add Course") if self.course_layout == None: self.course_layout = CourseInputDialog(self.user) self.course_layout.loaddashlayout.connect( lambda success: self.LoadDashboardLayout(success)) self.stack.addWidget(self.course_layout) self.stack.setCurrentWidget(self.course_layout) #sets dash movie layout as default layout (upload movie) def LoadDashMovieLayout(self, courseID): self.setWindowTitle("Add Movie") if self.addmovie_layout != None: self.stack.removeWidget(self.addmovie_layout) del self.addmovie_layout self.addmovie_layout = MovieInputDialog(self.user, courseID) self.addmovie_layout.goback_request.connect( lambda C_ID: self.LoadCourseMovies(C_ID)) self.stack.addWidget(self.addmovie_layout) self.stack.setCurrentWidget(self.addmovie_layout) def LoadCourseMovies(self, courseID): self.setWindowTitle("Course Movies") if self.CourseMovies_layout != None: self.stack.removeWidget(self.CourseMovies_layout) del self.CourseMovies_layout self.CourseMovies_layout = CourseMovieLayout(self.user, courseID) self.CourseMovies_layout.new_movie_request.connect( lambda C_ID: self.LoadDashMovieLayout(C_ID)) self.CourseMovies_layout.goback_request.connect( lambda success: self.LoadDashboardLayout(success)) self.CourseMovies_layout._WatchMovie_.connect( lambda url, M_ID: self.LoadMovieLayout(url, M_ID)) self.stack.addWidget(self.CourseMovies_layout) self.stack.setCurrentWidget(self.CourseMovies_layout) #ProfileLayout--------------------------------------------------------------------------------------------- #sets profile layout as default layout def LoadProfileLayout(self, success): self.setWindowTitle("Profile") if self.profile_layout != None: self.stack.removeWidget(self.profile_layout) del self.profile_layout self.profile_layout = ProfileLayout(self.user) self.profile_layout.changePass_request.connect( lambda: self.LoadChangePassLayout()) if (success == 1): self.profile_layout.errorMessage.setText( "Password Changed Successfully") self.stack.addWidget(self.profile_layout) self.stack.setCurrentWidget(self.profile_layout) self.silence() def LoadChangePassLayout(self): self.setWindowTitle("Change Password") if self.changepass_layout == None: self.changepass_layout = ChangePasswordLayout(self.user) self.changepass_layout.goback_request.connect( lambda success: self.LoadProfileLayout(success)) self.stack.addWidget(self.changepass_layout) self.stack.setCurrentWidget(self.changepass_layout) #----------------------------------------------------------------------------------------------------------- #stops movie from running in background (movie cleanup) def silence(self): if (self.movie_layout != None): self.movie_layout.Stop()
class SolveEquationWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) self.start = True self.resize(300, 200) self.layout = QStackedLayout() self.start_widget = QWidget() self.start_layout = QVBoxLayout() self._21equation = QPushButton('2 variables linear equation') self._21equation.clicked.connect( partial(self.create_solving_widget, 2, 3, func='line')) self._21equation.setMinimumHeight(80) change_font(self._21equation) self._31equation = QPushButton('3 variables linear equation') self._31equation.clicked.connect( partial(self.create_solving_widget, 3, 4, func='line')) self._31equation.setMinimumHeight(80) change_font(self._31equation) self._12equation = QPushButton('1 variables quadratic equation') self._12equation.clicked.connect( partial(self.create_solving_widget, 1, 3, func='quad')) self._12equation.setMinimumHeight(80) change_font(self._12equation) self.start_layout.addWidget(self._21equation) self.start_layout.addWidget(self._31equation) self.start_layout.addWidget(self._12equation) self.start_widget.setLayout(self.start_layout) self.layout.addWidget(self.start_widget) self.setLayout(self.layout) def create_solving_widget(self, row, column, func): self.func = func self.start = False self.solving_widget = QWidget() self.solving_layout = QVBoxLayout() return_button = Button('Return') return_button.clicked.connect(self.return_to_start_widget) self.solving_layout.addWidget(return_button) self.entries = [] for i in range(row): self.entries.append(QHBoxLayout()) for j in range(column): self.entries[i].addWidget(QLineEdit()) self.solving_layout.addLayout(self.entries[i]) result_hbox = QHBoxLayout() result_label = QLabel('Result') result_hbox.addWidget(result_label) self.result_num = [] if func == 'quad': row = 2 for i in range(row): self.result_num.append(QLabel()) result_hbox.addWidget(self.result_num[i]) self.solving_layout.addLayout(result_hbox) ok_button = Button('OK') ok_button.clicked.connect(self.solve) self.solving_layout.addWidget(ok_button) self.solving_widget.setLayout(self.solving_layout) self.layout.addWidget(self.solving_widget) self.layout.setCurrentIndex(1) def return_to_start_widget(self): self.start = True clear_layout(self.solving_layout) del self.solving_widget self.layout.removeWidget(self.layout.currentWidget()) self.layout.setCurrentIndex(0) def solve(self): para = [] for hbox in self.entries: for i in range(hbox.count()): para.append(evaluator.parse(hbox.itemAt(i).widget().text())) if self.func == 'line': result = linear_solver(*para) elif self.func == 'quad': result = quad_solver(*para) if result: for i in range(len(self.result_num)): self.result_num[i].setText(str(round(result[i], 11))) else: self.result_num[0].setText("No Answer") def keyPressEvent(self, event): if not self.start: if event.key() == Qt.Key_Enter: self.solve() @staticmethod def run(parent=None, position=None): w = SolveEquationWidget(parent) if position is not None: w.move(position) w.show()