def __addGenericTable(self, table): " Adds a generic table to the report " theTable = QTreeWidget(self.bodyWidget) theTable.setAlternatingRowColors(True) theTable.setRootIsDecorated(False) theTable.setItemsExpandable(False) theTable.setSortingEnabled(False) theTable.setItemDelegate(NoOutlineHeightDelegate(4)) theTable.setUniformRowHeights(True) headerLabels = [] for index in range(0, len(table.header)): headerLabels.append(table.header[index]) theTable.setHeaderLabels(headerLabels) for item in table.body: row = [] for index in range(0, len(table.header)): row.append(item[index]) theTable.addTopLevelItem(QTreeWidgetItem(row)) theTable.setFocusPolicy(Qt.NoFocus) # Resizing theTable.header().resizeSections(QHeaderView.ResizeToContents) theTable.header().setStretchLastSection(True) # Height self.__setTableHeight(theTable) self.__vLayout.addWidget(theTable) self.__widgets.append(theTable) return
def __addGenericTable( self, table ): " Adds a generic table to the report " theTable = QTreeWidget( self.bodyWidget ) theTable.setAlternatingRowColors( True ) theTable.setRootIsDecorated( False ) theTable.setItemsExpandable( False ) theTable.setSortingEnabled( False ) theTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) theTable.setUniformRowHeights( True ) headerLabels = [] for index in range( 0, len( table.header ) ): headerLabels.append( table.header[ index ] ) theTable.setHeaderLabels( headerLabels ) for item in table.body: row = [] for index in range( 0, len( table.header ) ): row.append( item[ index ] ) theTable.addTopLevelItem( QTreeWidgetItem( row ) ) theTable.setFocusPolicy( Qt.NoFocus ) # Resizing theTable.header().resizeSections( QHeaderView.ResizeToContents ) theTable.header().setStretchLastSection( True ) # Height self.__setTableHeight( theTable ) self.__vLayout.addWidget( theTable ) self.__widgets.append( theTable ) return
class AccountWidget(QWidget): def __init__(self, parent=None): super(AccountWidget, self).__init__(parent) # codeCompletionBlock start from PyQt4.QtGui import QTreeWidget, QStackedWidget self.dateTree = QTreeWidget() self.monthStack = QStackedWidget() # codeCompletionBlock end uic.loadUi(getUiFile('AccountWidget'), self) self.dateTree.currentItemChanged.connect(self.syncronizeStack) self.addTopLevelPeriod('CurrentTotal') def addNewSubaccount(self): data = self.inquireSubaccountData() print self def inquireSubaccountData(self): pass def addNextMonth(self): # treewidget get toplevel items # find last item # add new toplevvelitem if toplevel item has 12 subitems # add new sublevel item last = self.getLastItem() month = last.monthwidget self.dateTree.addMonth(month) def addSecondLevelPeriod(self, text): # TODO: find previous item item = self.dateTree.currentItem() if item: item.addChildren([QTreeWidgetItem([text])]) self.monthStack.addWidget(MonthWidget()) print self.getLastItem() def getLastItem(self): return MonthItem(1, MonthWidget()) def addTopLevelPeriod(self, text): self.monthStack.addWidget(MonthWidget()) item = QTreeWidgetItem([text]) self.dateTree.addTopLevelItem(item) self.dateTree.setCurrentItem(item) def syncronizeStack(self, item): print item
def __addErrorsTable(self, messages, showFileName): " Creates the messages table " errTable = QTreeWidget(self.bodyWidget) errTable.setAlternatingRowColors(True) errTable.setRootIsDecorated(False) errTable.setItemsExpandable(False) errTable.setSortingEnabled(True) errTable.setItemDelegate(NoOutlineHeightDelegate(4)) errTable.setUniformRowHeights(True) errTable.itemActivated.connect(self.__errorActivated) headerLabels = ["File name", "Line", "Message ID", "Object", "Message"] errTable.setHeaderLabels(headerLabels) for item in messages: if item.position is None: lineNumber = str(item.lineNumber) else: lineNumber = str(item.lineNumber) + ":" + str(item.position) values = [ item.fileName, lineNumber, item.messageID, item.objectName, item.message ] errTable.addTopLevelItem(ErrorTableItem(values, 1)) # Hide the file name column if required if not showFileName: errTable.setColumnHidden(0, True) # Resizing errTable.header().resizeSections(QHeaderView.ResizeToContents) errTable.header().setStretchLastSection(True) # Sort indicator if showFileName: sortIndex = 0 # By file names else: sortIndex = 1 # By line number because this is from the same file errTable.header().setSortIndicator(sortIndex, Qt.AscendingOrder) errTable.sortItems(sortIndex, errTable.header().sortIndicatorOrder()) # Height self.__setTableHeight(errTable) self.__vLayout.addWidget(errTable) self.__widgets.append(errTable) return
def __addErrorsTable( self, messages, showFileName ): " Creates the messages table " errTable = QTreeWidget( self.bodyWidget ) errTable.setAlternatingRowColors( True ) errTable.setRootIsDecorated( False ) errTable.setItemsExpandable( False ) errTable.setSortingEnabled( True ) errTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) errTable.setUniformRowHeights( True ) errTable.itemActivated.connect( self.__errorActivated ) headerLabels = [ "File name", "Line", "Message ID", "Object", "Message" ] errTable.setHeaderLabels( headerLabels ) for item in messages: if item.position is None: lineNumber = str( item.lineNumber ) else: lineNumber = str( item.lineNumber ) + ":" + str( item.position ) values = [ item.fileName, lineNumber, item.messageID, item.objectName, item.message ] errTable.addTopLevelItem( ErrorTableItem( values, 1 ) ) # Hide the file name column if required if not showFileName: errTable.setColumnHidden( 0, True ) # Resizing errTable.header().resizeSections( QHeaderView.ResizeToContents ) errTable.header().setStretchLastSection( True ) # Sort indicator if showFileName: sortIndex = 0 # By file names else: sortIndex = 1 # By line number because this is from the same file errTable.header().setSortIndicator( sortIndex, Qt.AscendingOrder ) errTable.sortItems( sortIndex, errTable.header().sortIndicatorOrder() ) # Height self.__setTableHeight( errTable ) self.__vLayout.addWidget( errTable ) self.__widgets.append( errTable ) return
class StackViewer( QWidget ): " Implements the stack viewer for a debugger " def __init__( self, debugger, parent = None ): QWidget.__init__( self, parent ) self.__debugger = debugger self.currentStack = None self.currentFrame = 0 self.__createPopupMenu() self.__createLayout() if Settings().showStackViewer == False: self.__onShowHide( True ) return def __createPopupMenu( self ): " Creates the popup menu " self.__framesMenu = QMenu() self.__setCurrentMenuItem = self.__framesMenu.addAction( "Set current (single click)", self.__onSetCurrent ) self.__jumpMenuItem = self.__framesMenu.addAction( "Set current and jump to the source (double click)", self.__onSetCurrentAndJump ) return def __createLayout( self ): " Creates the widget layout " verticalLayout = QVBoxLayout( self ) verticalLayout.setContentsMargins( 0, 0, 0, 0 ) verticalLayout.setSpacing( 0 ) self.headerFrame = QFrame() self.headerFrame.setFrameStyle( QFrame.StyledPanel ) self.headerFrame.setAutoFillBackground( True ) headerPalette = self.headerFrame.palette() headerBackground = headerPalette.color( QPalette.Background ) headerBackground.setRgb( min( headerBackground.red() + 30, 255 ), min( headerBackground.green() + 30, 255 ), min( headerBackground.blue() + 30, 255 ) ) headerPalette.setColor( QPalette.Background, headerBackground ) self.headerFrame.setPalette( headerPalette ) self.headerFrame.setFixedHeight( 24 ) self.__stackLabel = QLabel( "Stack" ) expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding ) fixedSpacer = QSpacerItem( 3, 3 ) self.__showHideButton = QToolButton() self.__showHideButton.setAutoRaise( True ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideButton.setFixedSize( 20, 20 ) self.__showHideButton.setToolTip( "Hide frames list" ) self.__showHideButton.setFocusPolicy( Qt.NoFocus ) self.__showHideButton.clicked.connect( self.__onShowHide ) headerLayout = QHBoxLayout() headerLayout.setContentsMargins( 0, 0, 0, 0 ) headerLayout.addSpacerItem( fixedSpacer ) headerLayout.addWidget( self.__stackLabel ) headerLayout.addSpacerItem( expandingSpacer ) headerLayout.addWidget( self.__showHideButton ) self.headerFrame.setLayout( headerLayout ) self.__framesList = QTreeWidget( self ) self.__framesList.setSortingEnabled( False ) # I might not need that because of two reasons: # - the window has no focus # - the window has custom current indicator # self.__framesList.setAlternatingRowColors( True ) self.__framesList.setRootIsDecorated( False ) self.__framesList.setItemsExpandable( False ) self.__framesList.setUniformRowHeights( True ) self.__framesList.setSelectionMode( QAbstractItemView.NoSelection ) self.__framesList.setSelectionBehavior( QAbstractItemView.SelectRows ) self.__framesList.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__framesList.setFocusPolicy( Qt.NoFocus ) self.__framesList.setContextMenuPolicy( Qt.CustomContextMenu ) self.__framesList.itemClicked.connect( self.__onFrameClicked ) self.__framesList.itemDoubleClicked.connect( self.__onFrameDoubleClicked ) self.__framesList.customContextMenuRequested.connect( self.__showContextMenu ) self.__framesList.setHeaderLabels( [ "", "File:line", "Function", "Full path" ] ) verticalLayout.addWidget( self.headerFrame ) verticalLayout.addWidget( self.__framesList ) return def __onShowHide( self, startup = False ): " Triggered when show/hide button is clicked " if startup or self.__framesList.isVisible(): self.__framesList.setVisible( False ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'more.png' ) ) self.__showHideButton.setToolTip( "Show frames list" ) self.__minH = self.minimumHeight() self.__maxH = self.maximumHeight() self.setMinimumHeight( self.headerFrame.height() ) self.setMaximumHeight( self.headerFrame.height() ) Settings().showStackViewer = False else: self.__framesList.setVisible( True ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideButton.setToolTip( "Hide frames list" ) self.setMinimumHeight( self.__minH ) self.setMaximumHeight( self.__maxH ) Settings().showStackViewer = True return def clear( self ): " Clears the content " self.__framesList.clear() self.currentStack = None self.__stackLabel.setText( "Stack" ) return def __resizeColumns( self ): " Resize the files list columns " self.__framesList.header().setStretchLastSection( True ) self.__framesList.header().resizeSections( QHeaderView.ResizeToContents ) self.__framesList.header().resizeSection( 0, 22 ) self.__framesList.header().setResizeMode( 0, QHeaderView.Fixed ) return def populate( self, stack ): " Sets the new call stack and selects the first item in it " self.clear() self.currentStack = stack self.currentFrame = 0 frameNumber = 0 for s in stack: if len( s ) == 2: # This is when an exception comes funcName = "" else: funcName = s[ 2 ] item = StackFrameItem( s[ 0 ], s[ 1 ], funcName, frameNumber ) self.__framesList.addTopLevelItem( item ) frameNumber += 1 self.__resizeColumns() self.__framesList.topLevelItem( 0 ).setCurrent( True ) self.__stackLabel.setText( "Stack (total: " + str( len( stack ) ) + ")" ) return def getFrameNumber( self ): " Provides the current frame number " return self.currentFrame def __onFrameClicked( self, item, column ): " Triggered when a frame is clicked " if item.isCurrent(): return # Hide the current indicator self.__framesList.topLevelItem( self.currentFrame ).setCurrent( False ) # Show the new indicator self.currentFrame = item.getFrameNumber() for index in xrange( self.__framesList.topLevelItemCount() ): item = self.__framesList.topLevelItem( index ) if item.getFrameNumber() == self.currentFrame: item.setCurrent( True ) self.__debugger.remoteClientVariables( 1, self.currentFrame ) # globals self.__debugger.remoteClientVariables( 0, self.currentFrame ) # locals return def __onFrameDoubleClicked( self, item, column ): " Triggered when a frame is double clicked " # The frame has been switched already because the double click # signal always comes after the single click one fileName = item.getFilename() lineNumber = item.getLineNumber() editorsManager = GlobalData().mainWindow.editorsManager() editorsManager.openFile( fileName, lineNumber ) editor = editorsManager.currentWidget().getEditor() editor.gotoLine( lineNumber ) editorsManager.currentWidget().setFocus() return def __showContextMenu( self, coord ): " Shows the frames list context menu " self.__contextItem = self.__framesList.itemAt( coord ) if self.__contextItem is not None: self.__setCurrentMenuItem.setEnabled( not self.__contextItem.isCurrent() ) self.__framesMenu.popup( QCursor.pos() ) return def __onSetCurrent( self ): " Context menu item handler " self.__onFrameClicked( self.__contextItem, 0 ) return def __onSetCurrentAndJump( self ): " Context menu item handler " self.__onFrameClicked( self.__contextItem, 0 ) self.__onFrameDoubleClicked( self.__contextItem, 0 ) return def switchControl( self, isInIDE ): " Switches the UI depending where the control flow is " self.__framesList.setEnabled( isInIDE ) return
class GmApp(QMainWindow): def __init__(self): super(QMainWindow, self).__init__() self.setWindowTitle("GuloMail by GulonSoft") self.setWindowIcon(QIcon("g-square.png")) self.createActions() self.createStatusBar() self.createMenus() self.createToolbars() self.createWidgets() self.createLayouts() def createActions(self): self.newAction=QAction("&New", self, shortcut=QKeySequence.New, statusTip="New") self.sendReceiveAction=QAction("Send / &Receive", self, shortcut="F9", statusTip="Send / Receive") self.printAction=QAction("&Print...", self, shortcut="Ctrl+P", statusTip="Print") self.quitAction=QAction("&Quit", self, shortcut="Ctrl+Q", statusTip="Quit", triggered=self.close) self.copyAction=QAction("&Copy", self, statusTip="Copy", shortcut=QKeySequence.Copy) self.deleteAction=QAction("&Delete", self, statusTip="Delete Message") self.nextAction=QAction("Next &Unread Message", self, shortcut="Ctrl+]", statusTip="Next unread message") self.previousAction=QAction("P&revious Unread Message", self, shortcut="Ctrl+[", statusTip="Previous unread message") self.replyAction=QAction("&Reply", self, shortcut="Ctrl+R", statusTip="Reply to sender", triggered=self.reply) self.replyToAllAction=QAction("Reply to &All", self, shortcut="Ctrl+Shift+R", statusTip="Reply to all", triggered=self.replyToAll) self.forwardAction=QAction("&Forward", self, shortcut="Ctrl+F", statusTip="Forward") self.junkAction=QAction("Junk", self, shortcut="Ctrl+J", statusTip="Mark as Junk") self.notJunkAction=QAction("Not junk", self, shortcut="Shift+Ctrl+J", statusTip="Mark as Not Junk") self.contentsAction=QAction("&Contents", self, statusTip="Help Contents", shortcut="F1", triggered=self.helpContents) self.aboutAction=QAction("&About", self, statusTip="About GuloMail", triggered=self.about) self.cancelAction=QAction("&Cancel", self, statusTip="Cancel") def createStatusBar(self): self.statusBar() def createMenus(self): self.fileMenu=self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.sendReceiveAction) self.fileMenu.addAction(self.printAction) self.fileMenu.addAction(self.quitAction) self.editMenu=self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.copyAction) self.editMenu.addAction(self.deleteAction) self.viewMenu=self.menuBar().addMenu("&View") self.folderMenu=self.menuBar().addMenu("F&older") self.messageMenu=self.menuBar().addMenu("&Message") self.goToMenu=self.messageMenu.addMenu("&Go To") self.goToMenu.addAction(self.nextAction) self.goToMenu.addAction(self.previousAction) self.messageMenu.addAction(self.replyAction) self.messageMenu.addAction(self.replyToAllAction) self.messageMenu.addAction(self.forwardAction) self.markAsMenu=self.messageMenu.addMenu("Mar&k as...") self.markAsMenu.addAction(self.junkAction) self.markAsMenu.addAction(self.notJunkAction) self.searchMenu=self.menuBar().addMenu("&Search") self.helpMenu=self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.contentsAction) self.helpMenu.addAction(self.aboutAction) def createToolbars(self): self.toolbar=self.addToolBar('Main Toolbar') self.toolbar.setMovable(False) self.toolbar.addAction(self.newAction) self.toolbar.addSeparator() self.toolbar.addAction(self.sendReceiveAction) self.toolbar.addSeparator() self.toolbar.addAction(self.replyAction) self.toolbar.addAction(self.replyToAllAction) self.toolbar.addAction(self.forwardAction) self.toolbar.addSeparator() self.toolbar.addAction(self.printAction) self.toolbar.addAction(self.deleteAction) self.toolbar.addAction(self.junkAction) self.toolbar.addAction(self.notJunkAction) self.toolbar.addAction(self.cancelAction) self.toolbar.addSeparator() self.toolbar.addAction(self.previousAction) self.toolbar.addAction(self.nextAction) def createWidgets(self): ## Message Table self.table=QTableView() self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setGridStyle(Qt.NoPen) self.model = QStandardItemModel(8, 3, self) self.model.setHeaderData(0, Qt.Horizontal, "From") self.model.setHeaderData(1, Qt.Horizontal, "Subject") self.model.setHeaderData(2, Qt.Horizontal, "Received") self.table.setModel(self.model) self.selectionModel = QItemSelectionModel(self.model) self.selectionModel.SelectionFlag=0x0020 self.table.setSelectionModel(self.selectionModel) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setSortingEnabled(True) self.table.setAlternatingRowColors(True) ## Folder Tree View self.folderTree=QTreeWidget() self.folderTree.setColumnCount(1) self.folderTree.setHeaderLabel(QString('Folders')) self.treeItem=QTreeWidgetItem() self.treeItem.setText(0, 'Folders') self.inbox=QTreeWidgetItem() self.inbox.setText(0, 'Inbox') self.deletedItems=QTreeWidgetItem() self.deletedItems.setText(0, 'Deleted Items') self.drafts=QTreeWidgetItem() self.drafts.setText(0, 'Drafts') self.junk=QTreeWidgetItem() self.junk.setText(0, 'Junk') self.outbox=QTreeWidgetItem() self.outbox.setText(0, 'Outbox') self.sent=QTreeWidgetItem() self.sent.setText(0, 'Sent') self.treeItem.addChild(self.inbox) self.treeItem.addChild(self.deletedItems) self.treeItem.addChild(self.drafts) self.treeItem.addChild(self.junk) self.treeItem.addChild(self.outbox) self.treeItem.addChild(self.sent) self.folderTree.addTopLevelItem(self.treeItem) self.folderTree.expandAll() self.folderTree.setAnimated(True) self.folderTree.setMaximumWidth(150) ## Temp. placeholders self.textEdit=QTextEdit() self.textEdit2=QTextEdit() def createLayouts(self): self.mainSplitter=QSplitter() self.setCentralWidget(self.mainSplitter) self.mainSplitter.addWidget(self.folderTree) self.messageSplitter=QSplitter(Qt.Vertical) self.messageSplitter.addWidget(self.table) self.messageSplitter.addWidget(self.textEdit2) self.mainSplitter.addWidget(self.messageSplitter) def helpContents(self): print "Help" def reply(self): print "Reply" def replyToAll(self): print "Reply To All" def about(self): text=QString("GuloMail v0.1\n\n") text.append("GuloMail is a freeware email client written in Python using PyQt4 (Python bindings for Nokia's Qt)\n\n") text.append(QChar(0x00A9)) text.append("GulonSoft 2010\nhttp://www.gulon.co.uk/") QMessageBox.about(self, "About GuloMail", text)
class Preferences(QDialog): configuration = {} weight = 0 def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(800, 600)) self.setMaximumSize(QSize(0, 0)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) self.connect(self.tree, SIGNAL("itemSelectionChanged()"), self._change_current) self.connect(self._btnCancel, SIGNAL("clicked()"), self.close) self.connect(self._btnSave, SIGNAL("clicked()"), self._save_preferences) self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0)) def _save_preferences(self): self.emit(SIGNAL("savePreferences()")) self.close() def load_ui(self): sections = sorted(list(Preferences.configuration.keys()), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) index = self.stacked.addWidget(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) #Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted(list(subcontent.keys()), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) index = self.stacked.addWidget(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) self.tree.expandAll() def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if not subsection: Preferences.configuration[section] = {'widget': widget, 'weight': weight, 'text': text} else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = {'widget': widget, 'weight': weight, 'text': text} config['subsections'] = subconfig Preferences.configuration[section] = config
class mainwindow(QtGui.QMainWindow): '''主窗体''' def __init__(self): super(mainwindow,self).__init__() self.setWindowTitle('组件设计工具') self.showMaximized() self.menuBar().show() self.createMenus() cwHLayout = QHBoxLayout() lLayout = QVBoxLayout() rLayout = QVBoxLayout() self.lw = QListWidget() self.lw.setSelectionMode(QAbstractItemView.SingleSelection ) lLayout.addWidget(self.lw) self.lw.itemSelectionChanged.connect(self.on_select) lGroup = QGroupBox('项目列表') lGroup.setLayout(lLayout) cwHLayout.addWidget(lGroup,2) cwHLayout.addLayout(rLayout,8) tLayout = QVBoxLayout() bLayout = QVBoxLayout() tGroup = QGroupBox('配置信息') self.bGroup = QGroupBox('生成代码') tGroup.setLayout(tLayout) self.bGroup.setLayout(bLayout) self.bGroup.setEnabled(False) rLayout.addWidget(tGroup) rLayout.addWidget(self.bGroup) self.tw_config = QTreeWidget() headerLabels = QStringList() headerLabels.append('项目') headerLabels.append('值') self.tw_config.setHeaderLabels(headerLabels) thLayout = QHBoxLayout() thLayout.addStretch(0) modify_btn = QPushButton('修改') modify_btn.clicked.connect(self.on_modify) del_btn = QPushButton('删除') del_btn.clicked.connect(self.on_del) thLayout.addWidget(modify_btn) thLayout.addWidget(del_btn) tLayout.addWidget(self.tw_config) tLayout.addLayout(thLayout) bhLayout = QHBoxLayout() bhLayout.addStretch(0) gen_btn = QPushButton('生成') gen_btn.clicked.connect(self.on_gen) bhLayout.addWidget(gen_btn) row1 = QHBoxLayout() lable1 = QLabel('工程名称:') self.et_project_name = QLineEdit() row1.addSpacing(10) row1.addWidget(lable1) row1.addWidget(self.et_project_name) row1.addStretch(0) row2 = QHBoxLayout() lable2 = QLabel('工程位置:') self.et_project_location = QLineEdit() self.et_project_location.setReadOnly(True) btn_location = QPushButton('...') btn_location.setFixedWidth(50) btn_location.clicked.connect(self.getProjectLocation) row2.addSpacing(10) row2.addWidget(lable2) row2.addWidget(self.et_project_location) row2.addWidget(btn_location) row2.addStretch(0) bLayout.addLayout(row1) bLayout.addLayout(row2) bLayout.addLayout(bhLayout) cw = QWidget() cw.setLayout(cwHLayout) self.setCentralWidget(cw) self._initByConfig() self.setMinimumSize(400,200) def _initByConfig(self): '''初始化''' pass def createMenus(self): '''创建菜单''' menueBar = self.menuBar() menuSys = menueBar.addMenu('系统') actNew = menuSys.addAction('新建工程') actOpen = menuSys.addAction('打开工程') actNew.triggered.connect(self.on_new) actOpen.triggered.connect(self.on_open) menueBar.addMenu(menuSys) def on_new(self): '''新建向导''' app.g_configurations = Configuration() # 用来渲染的配置数据 dlg = wizard.MyWizard() if dlg.exec_(): app.g_configurations.initialized = True app.g_projects.append(app.g_configurations) content = app.g_configurations.toJson() path = QFileDialog.getSaveFileName(self,"选择模板保存的路径", app.g_pwd + os.sep + "configurations" + os.sep + app.g_configurations.project_name + ".json" ,"Config (*.json)") if not path.isEmpty(): path = app.QString2str(path) with open(path,'w+') as f: f.write(content) self.lw.addItem(app.g_configurations.project_name) def getProjectLocation(self): '''获取项目路径''' path = QFileDialog.getExistingDirectory() path = QDir.fromNativeSeparators(path) self.et_project_location.setText(path) def on_open(self): '''打开现有配置''' fileName = QFileDialog.getOpenFileName(self,"选择现有模板",app.g_pwd + os.sep + "configurations","Config (*.json)") if fileName.isEmpty(): return with open(app.QString2str(fileName), 'r') as f: content = f.read() config = Configuration() config.fromJson(content) app.g_projects.append(config) self.lw.addItem(config.project_name) def on_del(self): index = self.lw.currentRow() if index < app.g_projects: self.bGroup.setEnabled(False) self.lw.takeItem(index) config = app.g_projects[index] app.g_projects.remove(config) self.tw_config.clear() return def on_select(self): '''选取配置''' index = self.lw.currentRow() if index < app.g_projects: self.bGroup.setEnabled(True) self.currentConfig = app.g_projects[index] self.showConfigInfo(self.currentConfig) def showConfigInfo(self,cf): '''显示配置信息''' self.tw_config.clear() self.et_project_name.setText(cf.project_name) self.et_project_location.setText(cf.project_location) sr = QStringList() sr.append('信息') root1 = QTreeWidgetItem(sr) sr = QStringList() sr.append('Qt库') root2 = QTreeWidgetItem(sr) sr = QStringList() sr.append('模块') root3 = QTreeWidgetItem(sr) sr = QStringList() sr.append('接口') root4 = QTreeWidgetItem(sr) self.tw_config.addTopLevelItem(root1) self.tw_config.addTopLevelItem(root2) self.tw_config.addTopLevelItem(root3) self.tw_config.addTopLevelItem(root4) sr1c00 = QStringList() sr1c00.append("项目名称") sr1c00.append(cf.project_name) r1c00 = QTreeWidgetItem(sr1c00) root1.addChild(r1c00) # sr1c0 = QStringList() # sr1c0.append("项目位置") # sr1c0.append(cf.project_location) # r1c0 = QTreeWidgetItem(sr1c0) # root1.addChild(r1c0) sr1c1 = QStringList() sr1c1.append("组件类型") sr1c1.append(cf.component_type) r1c1 = QTreeWidgetItem(sr1c1) root1.addChild(r1c1) sr1c2 = QStringList() sr1c2.append("源模板") sr1c2.append(cf.template_source) r1c2 = QTreeWidgetItem(sr1c2) root1.addChild(r1c2) sr1c3 = QStringList() sr1c3.append("平台类型") tmp_pt = "" if cf.platform_type & configuration.PT_WIN32: tmp_pt += "win32;" if cf.platform_type & configuration.PT_LINUX: tmp_pt += "linux" sr1c3.append(tmp_pt) r1c3 = QTreeWidgetItem(sr1c3) root1.addChild(r1c3) sr1c4 = QStringList() sr1c4.append("平台级别") sr1c4.append(cf.platform_version) r1c4 = QTreeWidgetItem(sr1c4) root1.addChild(r1c4) for qt in cf.qt_libs: sr2 = QStringList() sr2.append(qt['name']) sr2.append(qt['qt']) r2 = QTreeWidgetItem(sr2) root2.addChild(r2) for module in cf.modules: sr3 = QStringList() sr3.append(module['name']) sr3.append(module['description']) r3 = QTreeWidgetItem(sr3) root3.addChild(r3) for key in cf.interfaces.keys(): sr4 = QStringList() sr4.append(key) if cf.interfaces[key]: sr4.append('实现') else: sr4.append('未实现') r4 = QTreeWidgetItem(sr4) root4.addChild(r4) self.tw_config.expandAll() self.tw_config.header().resizeSection(0,300) def on_modify(self): '''修改配置''' if self.currentConfig: app.g_configurations = copy.copy(self.currentConfig) dlg = wizard.MyWizard() if dlg.exec_(): index = self.lw.currentRow() if index < app.g_projects: self.currentConfig = app.g_configurations app.g_projects[index] = self.currentConfig self.showConfigInfo(self.currentConfig) def on_gen(self): '''生成工程''' if not self.currentConfig: return #获取工程名及有效路径 project_name = self.et_project_name.text() project_location = self.et_project_location.text() qdir = QDir(project_location) if not qdir.exists(): if not qdir.mkpath(project_location): QMessageBox.warning(self, '警告', '路径无效!') return project_location = qdir.absolutePath() if not project_location.endsWith('/') and not project_location.endsWith('\\'): project_location += os.sep if project_name.isEmpty() or project_location.isEmpty(): QMessageBox.warning(self, '警告', '项目名称或路径不能为空!') return self.currentConfig.project_name = app.QString2str(project_name) self.currentConfig.project_location = app.QString2str(project_location) template_name = self.currentConfig.template_source template_dir = app.g_pwd + os.sep + 'templates' + os.sep + template_name with open(template_dir + os.sep + 'config.json', 'r') as f: self.currentConfig.config_content = f.read() ret_json = app.render(self.currentConfig.config_content, config=self.currentConfig) self.currentConfig.config = json.loads(ret_json) for file in self.currentConfig.config['files']: sourcepath = template_dir + os.sep + file['source'] targetdir = self.currentConfig.project_location + self.currentConfig.project_name targetpath = targetdir + os.sep + file['target'] fi = QFileInfo(targetpath) qdir = fi.absoluteDir() if not qdir.exists(): qdir.mkpath(fi.absolutePath()) with open(sourcepath, 'r') as f: content = f.read() content = app.render(content, config=self.currentConfig) #渲染文件 with open(targetpath, 'w+') as f: f.write(content.encode('utf-8')) QMessageBox.information(self,'提示','生成成功!')
class explorador(QDialog): def __init__(self): self.a = 0 super(explorador, self).__init__(None) self.setWindowTitle("Explorador de archivos y carpetas") self.resize(610, 450) self.back_history = [] self.forward_history = [] self.back = QPushButton('<-', self) self.back.clicked.connect(self.back_click) self.back.setGeometry(10, 10, 30, 20) self.back.setEnabled(False) self.forward = QPushButton('->', self) self.forward.clicked.connect(self.forward_click) self.forward.setGeometry(50, 10, 30, 20) self.forward.setEnabled(False) self.up = QPushButton('^', self) self.up.clicked.connect(self.up_button_click) self.up.setGeometry(90, 10, 30, 20) self.address = QLineEdit(self) self.address.setGeometry(130, 10, 420, 20) self.refresh = QPushButton('@', self) self.refresh.clicked.connect(self.refresh_click) self.refresh.setGeometry(560, 10, 30, 20) self.items = QTreeWidget(self) self.items.setRootIsDecorated(False) self.items.setHeaderLabels( ("Nombre", u"Fecha de modificación", u"Tamaño")) self.items.itemDoubleClicked.connect(self.item_double_clicked) self.items.setGeometry(5, 40, 600, 400) # Iniciar en el directorio actual. self.load_path(getcwd()) def back_click(self, checked): if self.back_history and len(self.back_history) > 1: # Obtener el último elemento. path = self.back_history[-2] self.forward_history.append(self.back_history[-1]) # Remover el directorio actual. del self.back_history[-1] self.load_path(path, False) def forward_click(self, checked): if self.forward_history: path = self.forward_history[-1] self.back_history.append(path) del self.forward_history[-1] self.load_path(path, False) def item_double_clicked(self, item, column): filepath = join(self.current_path, unicode(item.text(0))) if isdir(filepath): self.load_path(filepath) else: # Iniciar archivo con el programa predeterminado. #startfile(filepath) a = filepath #print a e = entrar() e.ponfoto(a) #parcial.ponfoto(a) #print self.a def up_button_click(self, checked): parent = dirname(self.current_path) if parent != self.current_path: self.load_path(parent) def load_path(self, path, use_history=True): # Obtener archivos y carpetas. items = listdir(unicode(path)) # Eliminar el contenido anterior. self.items.clear() for i in items: # Omitir archivos ocultos. if i.startswith("."): continue filepath = join(path, i) # Obtener informacion del archivo. stats = stat(filepath) # Crear el control ítem. item_widget = QTreeWidgetItem( (i, strftime("%c", localtime(stats.st_mtime)).decode("utf-8"), size(stats.st_size) if isfile(filepath) else "")) # Establecer el ícono correspondiente. item_widget.setIcon( 0, QIcon("images/%s.png" % ("file" if isfile(filepath) else "folder"))) # Añadir elemento. self.items.addTopLevelItem(item_widget) # Ajustar el tamaño de las columnas. for i in range(3): self.items.resizeColumnToContents(i) self.current_path = path self.address.setText(self.current_path) # Añadir al historial. if use_history: self.back_history.append(self.current_path) # Habilitar / dehabilitar botones del historial. if self.back_history and len(self.back_history) > 1: if not self.back.isEnabled(): self.back.setEnabled(True) else: if self.back.isEnabled(): self.forward_history = [] self.back.setEnabled(False) if self.forward_history: if not self.forward.isEnabled(): self.forward.setEnabled(True) else: if self.forward.isEnabled(): self.forward.setEnabled(False) def refresh_click(self, checked): self.load_path(self.current_path)
class PymetricsViewer(QWidget): " Pymetrics tab widget " # Limits to colorize the McCabe score LittleRiskLimit = 10 ModerateRiskLimit = 20 HighRiskLimit = 50 # Options of providing a report SingleFile = 0 DirectoryFiles = 1 ProjectFiles = 2 SingleBuffer = 3 def __init__(self, parent=None): QWidget.__init__(self, parent) self.__reportUUID = "" self.__reportFileName = "" self.__reportOption = -1 self.__reportShown = False self.__report = None # Prepare members for reuse self.__noneLabel = QLabel("\nNo results available") self.__noneLabel.setFrameShape(QFrame.StyledPanel) self.__noneLabel.setAlignment(Qt.AlignHCenter) self.__headerFont = self.__noneLabel.font() self.__headerFont.setPointSize(self.__headerFont.pointSize() + 4) self.__noneLabel.setFont(self.__headerFont) self.__noneLabel.setAutoFillBackground(True) noneLabelPalette = self.__noneLabel.palette() noneLabelPalette.setColor(QPalette.Background, GlobalData().skin.nolexerPaper) self.__noneLabel.setPalette(noneLabelPalette) self.__createLayout(parent) self.__updateButtonsStatus() return def __createLayout(self, parent): " Creates the toolbar and layout " # Buttons self.__mcCabeButton = QAction(PixmapCache().getIcon('tableview.png'), 'Switch to McCabe only table view', self) self.__mcCabeButton.setCheckable(True) self.connect(self.__mcCabeButton, SIGNAL('toggled(bool)'), self.__onMcCabe) self.printButton = QAction(PixmapCache().getIcon('printer.png'), 'Print', self) #printButton.setShortcut( 'Ctrl+' ) self.connect(self.printButton, SIGNAL('triggered()'), self.__onPrint) self.printButton.setVisible(False) self.printPreviewButton = QAction( PixmapCache().getIcon('printpreview.png'), 'Print preview', self) #printPreviewButton.setShortcut( 'Ctrl+' ) self.connect(self.printPreviewButton, SIGNAL('triggered()'), self.__onPrintPreview) self.printPreviewButton.setVisible(False) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.clearButton = QAction(PixmapCache().getIcon('trash.png'), 'Clear', self) self.connect(self.clearButton, SIGNAL('triggered()'), self.__clear) # The toolbar self.toolbar = QToolBar(self) self.toolbar.setOrientation(Qt.Vertical) self.toolbar.setMovable(False) self.toolbar.setAllowedAreas(Qt.RightToolBarArea) self.toolbar.setIconSize(QSize(16, 16)) self.toolbar.setFixedWidth(28) self.toolbar.setContentsMargins(0, 0, 0, 0) self.toolbar.addAction(self.__mcCabeButton) self.toolbar.addAction(self.printPreviewButton) self.toolbar.addAction(self.printButton) self.toolbar.addWidget(spacer) self.toolbar.addAction(self.clearButton) self.__totalResultsTree = QTreeWidget() self.__totalResultsTree.setAlternatingRowColors(True) self.__totalResultsTree.setRootIsDecorated(True) self.__totalResultsTree.setItemsExpandable(True) self.__totalResultsTree.setUniformRowHeights(True) self.__totalResultsTree.setItemDelegate(NoOutlineHeightDelegate(4)) headerLabels = ["Path / name", "Value", ""] self.__totalResultsTree.setHeaderLabels(headerLabels) self.connect(self.__totalResultsTree, SIGNAL("itemActivated(QTreeWidgetItem *, int)"), self.__allItemActivated) self.connect(self.__totalResultsTree, SIGNAL("itemExpanded(QTreeWidgetItem *)"), self.__onResultsExpanded) self.__totalResultsTree.setColumnHidden(2, True) self.__totalResultsTree.hide() self.__mcCabeTable = QTreeWidget() self.__mcCabeTable.setAlternatingRowColors(True) self.__mcCabeTable.setRootIsDecorated(False) self.__mcCabeTable.setItemsExpandable(False) self.__mcCabeTable.setSortingEnabled(True) self.__mcCabeTable.setItemDelegate(NoOutlineHeightDelegate(4)) self.__mcCabeTable.setUniformRowHeights(True) headerLabels = ["", "File name", "Object", "McCabe Complexity"] self.__mcCabeTable.setHeaderLabels(headerLabels) self.connect(self.__mcCabeTable, SIGNAL("itemActivated(QTreeWidgetItem *, int)"), self.__mcCabeActivated) self.__mcCabeTable.hide() self.__hLayout = QHBoxLayout() self.__hLayout.setContentsMargins(0, 0, 0, 0) self.__hLayout.setSpacing(0) self.__hLayout.addWidget(self.toolbar) self.__hLayout.addWidget(self.__noneLabel) self.__hLayout.addWidget(self.__totalResultsTree) self.__hLayout.addWidget(self.__mcCabeTable) self.setLayout(self.__hLayout) return def getTotalResultsWidget(self): " Provides a reference to the total results widget " return self.__totalResultsTree def getMcCabeResultsWidget(self): " Provides a reference to the McCabe results widget " return self.__mcCabeTable def __updateButtonsStatus(self): " Updates the buttons status " self.__mcCabeButton.setEnabled(self.__reportShown) self.printButton.setEnabled(self.__reportShown) self.printPreviewButton.setEnabled(self.__reportShown) self.clearButton.setEnabled(self.__reportShown) return def __onResultsExpanded(self, item): " An item has been expanded, so the column width should be adjusted " self.__totalResultsTree.header().resizeSections( QHeaderView.ResizeToContents) return def __onPrint(self): " Triggered when the print button is pressed " pass def __onPrintPreview(self): " triggered when the print preview button is pressed " pass def __onMcCabe(self, state): " Triggered when the metrics view is switched " if not self.__reportShown: return if state: self.__totalResultsTree.hide() self.__mcCabeTable.show() self.__mcCabeButton.setIcon(PixmapCache().getIcon('treeview.png')) self.__mcCabeButton.setToolTip("Switch to complete " "results tree view") else: self.__mcCabeTable.hide() self.__totalResultsTree.show() self.__mcCabeButton.setIcon(PixmapCache().getIcon('tableview.png')) self.__mcCabeButton.setToolTip("Switch to McCabe only table view") return def setFocus(self): " Overridden setFocus " self.__hLayout.setFocus() return def __clear(self): " Clears the content of the vertical layout " if not self.__reportShown: return self.__totalResultsTree.clear() self.__totalResultsTree.hide() self.__mcCabeTable.clear() self.__mcCabeTable.hide() self.__noneLabel.show() self.__report = None self.__reportShown = False self.__updateButtonsStatus() # self.resizeEvent() self.__mcCabeButton.setIcon(PixmapCache().getIcon('tableview.png')) self.__mcCabeButton.setToolTip("Switch to McCabe only table view") self.__mcCabeButton.setChecked(False) self.__updateTooltip() return def __updateTooltip(self): " Generates a signal with appropriate string message " if not self.__reportShown: tooltip = "No metrics available" elif self.__reportOption == self.DirectoryFiles: tooltip = "Metrics generated for directory: " + \ self.__reportFileName elif self.__reportOption == self.ProjectFiles: tooltip = "Metrics generated for the whole project" elif self.__reportOption == self.SingleFile: tooltip = "Metrics generated for file: " + self.__reportFileName elif self.__reportOption == self.SingleBuffer: tooltip = "Metrics generated for unsaved file: " + \ self.__reportFileName else: tooltip = "" self.emit(SIGNAL('updatePymetricsTooltip'), tooltip) return @staticmethod def __shouldShowFileName(table, column): " Checks if the file name is the same " size = table.topLevelItemCount() if size == 0: return False index = size - 1 firstName = table.topLevelItem(index).text(column) index -= 1 while index >= 0: if table.topLevelItem(index).text(column) != firstName: return True index -= 1 return False def showReport(self, metrics, reportOption, fileName, uuid): " Shows the pymetrics results " self.__clear() self.__noneLabel.hide() self.__report = metrics self.__reportUUID = uuid self.__reportFileName = fileName self.__reportOption = reportOption if len(metrics.report) > 1: accumulatedBasic = self.__accumulateBasicMetrics() accItem = QTreeWidgetItem(["Cumulative basic metrics"]) self.__totalResultsTree.addTopLevelItem(accItem) for key in accumulatedBasic: bmItem = [ BasicMetrics.metricsOfInterest[key], splitThousands(str(accumulatedBasic[key])) ] basicMetric = QTreeWidgetItem(bmItem) accItem.addChild(basicMetric) # Add the complete information for fileName in metrics.report: if reportOption == self.SingleBuffer: fileItem = QTreeWidgetItem(["Editor buffer"]) else: fileItem = QTreeWidgetItem([fileName]) info = GlobalData().briefModinfoCache.get(fileName) if info.docstring is not None: fileItem.setToolTip(0, info.docstring.text) else: fileItem.setToolTip(0, "") self.__totalResultsTree.addTopLevelItem(fileItem) # Messages part messages = metrics.report[fileName].messages if len(messages) > 0: messagesItem = QTreeWidgetItem(["Messages"]) fileItem.addChild(messagesItem) for message in messages: mItem = [message, "", "E"] messagesItem.addChild(QTreeWidgetItem(mItem)) # Basic metrics part basicItem = QTreeWidgetItem(["Basic metrics"]) fileItem.addChild(basicItem) basic = metrics.report[fileName].basicMetrics for key in basic.metrics: bmItem = [ BasicMetrics.metricsOfInterest[key], str(basic.metrics[key]) ] basicMetric = QTreeWidgetItem(bmItem) basicItem.addChild(basicMetric) # McCabe part mccabeItem = QTreeWidgetItem(["McCabe metrics"]) fileItem.addChild(mccabeItem) mccabe = metrics.report[fileName].mcCabeMetrics.metrics for objName in mccabe: objItem = [objName, str(mccabe[objName]), "M"] mccabeMetric = QTreeWidgetItem(objItem) mccabeItem.addChild(mccabeMetric) # COCOMO 2 part cocomo = [ "COCOMO 2", str(metrics.report[fileName].cocomo2Metrics.value) ] cocomoItem = QTreeWidgetItem(cocomo) fileItem.addChild(cocomoItem) # Resizing the table self.__totalResultsTree.header().resizeSections( QHeaderView.ResizeToContents) # Add McCabe complexity information for fileName in metrics.report: mccabe = metrics.report[fileName].mcCabeMetrics.metrics for objName in mccabe: values = ["", fileName, objName, str(mccabe[objName])] self.__mcCabeTable.addTopLevelItem(McCabeTableItem(values)) if not self.__shouldShowFileName(self.__mcCabeTable, 1): self.__mcCabeTable.setColumnHidden(1, True) # Resizing and sorting the table self.__mcCabeTable.header().setSortIndicator(3, Qt.DescendingOrder) self.__mcCabeTable.sortItems( 3, self.__mcCabeTable.header().sortIndicatorOrder()) self.__mcCabeTable.header().resizeSections( QHeaderView.ResizeToContents) # Show the complete information self.__mcCabeTable.hide() self.__totalResultsTree.show() self.__reportShown = True self.__updateButtonsStatus() self.__updateTooltip() # It helps, but why do I have flickering? QApplication.processEvents() return def __accumulateBasicMetrics(self): " Accumulates basic metrics for all the processed files " basic = {} for fileName in self.__report.report: singleBasic = self.__report.report[fileName].basicMetrics.metrics for key in singleBasic: if not key.startswith('num'): continue if key in basic: basic[key] += int(singleBasic[key]) else: basic[key] = int(singleBasic[key]) return basic def __mcCabeActivated(self, item, column): " Handles the double click (or Enter) on the mccabe table item " objName = str(item.text(2)) if self.__reportOption == self.SingleBuffer: if os.path.isabs(self.__reportFileName): fileName = self.__reportFileName else: fileName = "" else: fileName = str(item.text(1)) self.__onMcCabeObject(objName, fileName) return def __allItemActivated(self, item, column): " Handles the double click (or Enter) in the total results tree " # We process only the error messages and McCabe items hiddenColumnText = str(item.text(2)) if not hiddenColumnText in ["M", "E"]: return fileName = self.__getTreeItemFileName(item) lineNumber = 0 if hiddenColumnText == "M": # This is McCabe item objName = str(item.text(0)) self.__onMcCabeObject(objName, fileName) return elif hiddenColumnText == "E": # This is an error message message = str(item.text(0)) pos = message.find("at line") if pos == -1: logging.error("Unknown format of the message. " "Please inform the developers.") return parts = message[pos:].split() try: lineNumber = int(parts[2].replace(',', '')) except: logging.error("Unknown format of the message. " "Please inform the developers.") return if fileName == "": # This is an unsaved buffer, try to find the editor by UUID mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetByUUID(self.__reportUUID) if widget is None: logging.error("The unsaved buffer has been closed") return # The widget was found, so jump to the required editor = widget.getEditor() editor.gotoLine(lineNumber) editor.setFocus() return GlobalData().mainWindow.openFile(fileName, lineNumber) return def __getTreeItemFileName(self, item): " Identifies the tree view item file name " if self.__reportOption == self.SingleBuffer: if os.path.isabs(self.__reportFileName): return self.__reportFileName return "" # The file name is always two levels up fileItem = item.parent().parent() return str(fileItem.text(0)) def __onMcCabeObject(self, objName, fileName): " Called when the user activated McCabe item " info = None mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetByUUID(self.__reportUUID) if widget is None: if fileName == "": logging.error("The unsaved buffer has been closed") return # No widget, but we know the file name info = getBriefModuleInfoFromFile(fileName) else: # The widget was found editor = widget.getEditor() # The editor content has been modified, so re-parse the buffer info = getBriefModuleInfoFromMemory(editor.text()) parts = objName.split('.') currentIndex = 0 functionsContainer = info.functions classesContainer = info.classes line = -1 if objName == "__main__" and len(parts) == 1: # Special case - global file scope line = 1 currentIndex = 1 while currentIndex < len(parts): found = False for func in functionsContainer: if func.name == parts[currentIndex]: if currentIndex == len(parts) - 1: # Found, jump to the line line = func.line break functionsContainer = func.functions classesContainer = func.classes found = True break if line != -1: break if found: currentIndex += 1 continue for klass in classesContainer: if klass.name == parts[currentIndex]: if currentIndex == len(parts) - 1: # Found, jump to the line line = klass.line break functionsContainer = klass.functions classesContainer = klass.classes found = True if line != -1: break if found: currentIndex += 1 continue # Not found logging.error("Cannot find the " + objName) return # Here we have the line number if widget is None: GlobalData().mainWindow.openFile(fileName, line) else: editor = widget.getEditor() editor.gotoLine(line) editor.setFocus() return def onFileUpdated(self, fileName, uuid): " Called when a buffer is saved or saved as " if not self.__reportShown: return if self.__reportUUID != uuid: return # Currently shown report is for the saved buffer # File name is expected being absolute self.__reportFileName = fileName self.emit(SIGNAL('updatePymetricsTooltip'), "Metrics generated for buffer saved as " + fileName) return
def load(filename, widget): """Loads snippets from a file, displaying them in a list. The user can then choose: - overwrite builtin snippets or not - overwrite own snippets with same title or not - select and view snippets contents. """ try: d = ET.parse(filename) elements = list(d.findall('snippet')) if not elements: raise ValueError(_("No snippets found.")) except Exception as e: QMessageBox.critical(widget, app.caption(_("Error")), _("Can't read from source:\n\n{url}\n\n{error}").format( url=filename, error=e)) return dlg = widgets.dialog.Dialog(widget) dlg.setWindowModality(Qt.WindowModal) dlg.setWindowTitle(app.caption(_("dialog title", "Import Snippets"))) tree = QTreeWidget(headerHidden=True, rootIsDecorated=False) dlg.setMainWidget(tree) userguide.addButton(dlg.buttonBox(), "snippet_import_export") allnames = frozenset(snippets.names()) builtins = frozenset(builtin.builtin_snippets) titles = dict((snippets.title(n), n) for n in allnames if n not in builtins) new = QTreeWidgetItem(tree, [_("New Snippets")]) updated = QTreeWidgetItem(tree, [_("Updated Snippets")]) unchanged = QTreeWidgetItem(tree, [_("Unchanged Snippets")]) new.setFlags(Qt.ItemIsEnabled) updated.setFlags(Qt.ItemIsEnabled) unchanged.setFlags(Qt.ItemIsEnabled) new.setExpanded(True) updated.setExpanded(True) items = [] for snip in elements: item = QTreeWidgetItem() item.body = snip.find('body').text item.title = snip.find('title').text item.shortcuts = list(e.text for e in snip.findall('shortcuts/shortcut')) title = item.title or snippets.maketitle(snippets.parse(item.body).text) item.setText(0, title) name = snip.get('id') name = name if name in builtins else None # determine if new, updated or unchanged if not name: name = titles.get(title) item.name = name if not name or name not in allnames: new.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) elif name: if (item.body != snippets.text(name) or title != snippets.title(name) or (item.shortcuts and item.shortcuts != [s.toString() for s in model.shortcuts(name) or ()])): updated.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) else: unchanged.addChild(item) item.setFlags(Qt.ItemIsEnabled) # count: for i in new, updated, unchanged: i.setText(0, i.text(0) + " ({0})".format(i.childCount())) for i in new, updated: if i.childCount(): i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) i.setCheckState(0, Qt.Checked) def changed(item): if item in (new, updated): for i in range(item.childCount()): c = item.child(i) c.setCheckState(0, item.checkState(0)) tree.itemChanged.connect(changed) importShortcuts = QTreeWidgetItem([_("Import Keyboard Shortcuts")]) if items: tree.addTopLevelItem(importShortcuts) importShortcuts.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) importShortcuts.setCheckState(0, Qt.Checked) dlg.setMessage(_("Choose which snippets you want to import:")) else: dlg.setMessage(_("There are no new or updated snippets in the file.")) unchanged.setExpanded(True) tree.setWhatsThis(_( "<p>Here the snippets from {filename} are displayed.</p>\n" "<p>If there are new or updated snippets, you can select or deselect " "them one by one, or all at once, using the checkbox of the group. " "Then click OK to import all the selected snippets.</p>\n" "<p>Existing, unchanged snippets can't be imported.</p>\n" ).format(filename=os.path.basename(filename))) qutil.saveDialogSize(dlg, "snippettool/import/size", QSize(400, 300)) if not dlg.exec_() or not items: return ac = model.collection() m = model.model() with qutil.busyCursor(): for i in items: if i.checkState(0) == Qt.Checked: index = m.saveSnippet(i.name, i.body, i.title) if i.shortcuts and importShortcuts.checkState(0): shortcuts = list(map(QKeySequence.fromString, i.shortcuts)) ac.setShortcuts(m.name(index), shortcuts) widget.updateColumnSizes()
class Window(QMainWindow): iso_format = "%Y-%m-%d %H:%M:%S" def __init__(self, controller, parent = None): QMainWindow.__init__(self, parent) self.controller = controller self.modelsList = QTreeWidget() self.modelsList.setColumnCount(1) self.modelsList.setHeaderHidden(True) self.modelsList.currentItemChanged.connect(self._setModelFromItem) self.fieldsList = QTreeWidget() self.fieldsList.setColumnCount(1) self.fieldsList.setHeaderHidden(True) self.fieldsList.currentItemChanged.connect(self._setFieldFromItem) self.timesList = QTreeWidget() self.timesList.setColumnCount(1) self.timesList.setHeaderHidden(True) self.timesList.currentItemChanged.connect(self._setPlotTimeFromItem) modelsDock = QDockWidget(self.tr("Models")) modelsDock.setWidget(self.modelsList) self.addDockWidget(Qt.LeftDockWidgetArea, modelsDock) fieldsDock = QDockWidget(self.tr("Fields")) fieldsDock.setWidget(self.fieldsList) self.addDockWidget(Qt.RightDockWidgetArea, fieldsDock) timesDock = QDockWidget(self.tr("Times")) timesDock.setWidget(self.timesList) self.addDockWidget(Qt.LeftDockWidgetArea, timesDock) fileMenu = self.menuBar().addMenu(self.tr("&File")) quitAction = fileMenu.addAction(self.tr("E&xit")) quitAction.setShortcut(QKeySequence.Quit) quitAction.triggered.connect(self.close) dockMenu = self.menuBar().addMenu(self.tr("&Docks")) dockMenu.addAction(modelsDock.toggleViewAction()) dockMenu.addAction(fieldsDock.toggleViewAction()) dockMenu.addAction(timesDock.toggleViewAction()) work_area = WorkArea(controller) self.setCentralWidget(work_area) def readModels(self): info_list = self.controller.initFieldDialog() self.modelsList.clear() for info in info_list: item = QTreeWidgetItem() item.setText(0, info.groupName) self.modelsList.addTopLevelItem(item) for model in info.modelNames: child = QTreeWidgetItem() child.setText(0, model) item.addChild(child) def readFields(self): refTimes = list(self.controller.getFieldReferenceTimes(self.model)) if not refTimes: return refTimes.sort() model, fieldGroups = self.controller.getFieldGroups(self.model, refTimes[-1], False) self.fieldsList.clear() fields = set() for group in fieldGroups: for field in group.fieldNames: fields.add(field) fields = list(fields) fields.sort() for field in fields: item = QTreeWidgetItem() item.setText(0, field) self.fieldsList.addTopLevelItem(item) def _setModelFromItem(self, current): if current: model = current.text(0) self.setModel(model) def _setFieldFromItem(self, current): if current: field = current.text(0) self.setField(str(field)) def _setPlotTimeFromItem(self, current): if current: time = current.data(0, Qt.UserRole).toPyObject() self.setPlotTime(time) def setModel(self, model): self.model = str(model) self.readFields() def setField(self, field): self.field = field request = FieldRequest() request.modelName = self.model request.paramName = field times = self.controller.getFieldTime([request]) times.sort() self.updateTimes(times) def setPlotTime(self, time): self.time = time self.plot() def _updateTimesFromPlot(self, times): t = [] self.timesList.clear() for key, values in times.items(): for value in values: t.append((value, key)) t.sort() self.updateTimes(self, times) def updateTimes(self, times): self.timesList.clear() for value in times: item = QTreeWidgetItem() item.setText(0, value.strftime(self.iso_format)) item.setData(0, Qt.UserRole, value) self.timesList.addTopLevelItem(item) self.timesList.resizeColumnToContents(0) def selectTime(self, time): i = 0 while i < self.timesList.topLevelItemCount(): item = self.timesList.topLevelItem(i) if item.text(0) == time.strftime(self.iso_format): self.timesList.setCurrentItem(item) return i += 1 def plot(self): self.field_plots = ["FIELD model=%s plot=%s plottype=fill_cell" % (self.model, self.field)] l = ['AREA name=model/sat-area', 'MAP backcolour=white map=Gshhs-Auto contour=on ' 'cont.colour=black cont.linewidth=1 cont.linetype=solid ' 'cont.zorder=1 land=on land.colour=flesh land.zorder=0 ' 'lon=off lat=off frame=off'] + self.field_plots self.controller.plotCommands(l) #times = self.controller.getPlotTimes() #self._updateTimesFromPlot(times) # #for key, values in times.items(): # if values: # self.selectTime(values[-1]) # break #else: self.controller.setPlotTime(self.time) self.controller.updatePlots() self.update()
def load(filename, widget): """Loads snippets from a file, displaying them in a list. The user can then choose: - overwrite builtin snippets or not - overwrite own snippets with same title or not - select and view snippets contents. """ try: d = ET.parse(filename) elements = list(d.findall('snippet')) if not elements: raise ValueError(_("No snippets found.")) except Exception as e: QMessageBox.critical( widget, app.caption(_("Error")), _("Can't read from source:\n\n{url}\n\n{error}").format( url=filename, error=e)) return dlg = widgets.dialog.Dialog(widget) dlg.setWindowModality(Qt.WindowModal) dlg.setWindowTitle(app.caption(_("dialog title", "Import Snippets"))) tree = QTreeWidget(headerHidden=True, rootIsDecorated=False) dlg.setMainWidget(tree) userguide.addButton(dlg.buttonBox(), "snippet_import_export") allnames = frozenset(snippets.names()) builtins = frozenset(builtin.builtin_snippets) titles = dict( (snippets.title(n), n) for n in allnames if n not in builtins) new = QTreeWidgetItem(tree, [_("New Snippets")]) updated = QTreeWidgetItem(tree, [_("Updated Snippets")]) unchanged = QTreeWidgetItem(tree, [_("Unchanged Snippets")]) new.setFlags(Qt.ItemIsEnabled) updated.setFlags(Qt.ItemIsEnabled) unchanged.setFlags(Qt.ItemIsEnabled) new.setExpanded(True) updated.setExpanded(True) items = [] for snip in elements: item = QTreeWidgetItem() item.body = snip.find('body').text item.title = snip.find('title').text item.shortcuts = list(e.text for e in snip.findall('shortcuts/shortcut')) title = item.title or snippets.maketitle( snippets.parse(item.body).text) item.setText(0, title) name = snip.get('id') name = name if name in builtins else None # determine if new, updated or unchanged if not name: name = titles.get(title) item.name = name if not name or name not in allnames: new.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) elif name: if (item.body != snippets.text(name) or title != snippets.title(name) or (item.shortcuts and item.shortcuts != [s.toString() for s in model.shortcuts(name) or ()])): updated.addChild(item) items.append(item) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) item.setCheckState(0, Qt.Checked) else: unchanged.addChild(item) item.setFlags(Qt.ItemIsEnabled) # count: for i in new, updated, unchanged: i.setText(0, i.text(0) + " ({0})".format(i.childCount())) for i in new, updated: if i.childCount(): i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) i.setCheckState(0, Qt.Checked) def changed(item): if item in (new, updated): for i in range(item.childCount()): c = item.child(i) c.setCheckState(0, item.checkState(0)) tree.itemChanged.connect(changed) importShortcuts = QTreeWidgetItem([_("Import Keyboard Shortcuts")]) if items: tree.addTopLevelItem(importShortcuts) importShortcuts.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable) importShortcuts.setCheckState(0, Qt.Checked) dlg.setMessage(_("Choose which snippets you want to import:")) else: dlg.setMessage(_("There are no new or updated snippets in the file.")) unchanged.setExpanded(True) tree.setWhatsThis( _("<p>Here the snippets from {filename} are displayed.</p>\n" "<p>If there are new or updated snippets, you can select or deselect " "them one by one, or all at once, using the checkbox of the group. " "Then click OK to import all the selected snippets.</p>\n" "<p>Existing, unchanged snippets can't be imported.</p>\n").format( filename=os.path.basename(filename))) qutil.saveDialogSize(dlg, "snippettool/import/size", QSize(400, 300)) if not dlg.exec_() or not items: return ac = model.collection() m = model.model() with qutil.busyCursor(): for i in items: if i.checkState(0) == Qt.Checked: index = m.saveSnippet(i.name, i.body, i.title) if i.shortcuts and importShortcuts.checkState(0): shortcuts = list(map(QKeySequence.fromString, i.shortcuts)) ac.setShortcuts(m.name(index), shortcuts) widget.updateColumnSizes()
class DBServersWidget(QWidget): """Displays a list of servers""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.connections = {} self.setWindowTitle("Servers") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(True) self.tree.setHeaderLabels(["Server", "Butt"]) # set header, but hide anyway self.tree.header().hide() self.tree.header().setResizeMode(C.node, QHeaderView.Stretch) self.tree.setColumnWidth(C.butt, 20) self.connect( self.tree, SIGNAL( 'itemSelectionChanged()' ), self.on_tree_selection_changed ) self.connect( self.tree, SIGNAL( 'itemDoubleClicked (QTreeWidgetItem *,int)' ), self.on_tree_double_clicked ) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.node, srv['server']) #item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.butt, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers() def on_open_server(self, butt): # self.emit(SIGNAL("open_server"), butt.property("server").toString()) srv_ki = str(butt.property("server").toString()) server = G.settings.get_server(srv_ki) db = QSqlDatabase.addDatabase("QMYSQL", srv_ki) db.setHostName(server['server']) db.setUserName(server['user']) db.setPassword(server['passwd']) ok = db.open() if ok: #self.connections[srv_ki] = self.load_databases(srv_ki) print "open", ok def load_databases(self, srv_ki): """Load databases into tree node for server; executes 'show databases;' or aslike """ sql = "show databases;" query = QSqlQuery(QSqlDatabase.database(srv_ki)) ok = query.exec_(sql) print ok, sql, query.result() # Get the parent node, ie the server node pItem = self.tree.findItems(srv_ki, Qt.MatchExactly, C.node)[0] ## Assumed value(0) is the table.. we need the defs (ie mysql case) while query.next(): table_name = query.value(0).toString() nuItem = QTreeWidgetItem(pItem) nuItem.setText(C.node, table_name) #print table_name self.tree.setItemExpanded(pItem, True)
class FontsColors(preferences.Page): def __init__(self, dialog): super(FontsColors, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.printScheme = QCheckBox() layout.addWidget(self.printScheme) hbox = QHBoxLayout() self.tree = QTreeWidget(self) self.tree.setHeaderHidden(True) self.tree.setAnimated(True) self.stack = QStackedWidget(self) hbox.addWidget(self.tree) hbox.addWidget(self.stack) layout.addLayout(hbox) hbox = QHBoxLayout() self.fontLabel = QLabel() self.fontChooser = QFontComboBox() self.fontSize = QDoubleSpinBox() self.fontSize.setRange(6.0, 32.0) self.fontSize.setSingleStep(0.5) self.fontSize.setDecimals(1) hbox.addWidget(self.fontLabel) hbox.addWidget(self.fontChooser, 1) hbox.addWidget(self.fontSize) layout.addLayout(hbox) # add the items to our list self.baseColorsItem = i = QTreeWidgetItem() self.tree.addTopLevelItem(i) self.defaultStylesItem = i = QTreeWidgetItem() self.tree.addTopLevelItem(i) self.defaultStyles = {} for name in textformats.defaultStyles: self.defaultStyles[name] = i = QTreeWidgetItem() self.defaultStylesItem.addChild(i) i.name = name self.defaultStylesItem.setExpanded(True) self.allStyles = {} for group, styles in ly.colorize.default_mapping(): i = QTreeWidgetItem() children = {} self.allStyles[group] = (i, children) self.tree.addTopLevelItem(i) i.group = group for name, base, clss in styles: j = QTreeWidgetItem() j.name = name j.base = base i.addChild(j) children[name] = j self.baseColorsWidget = BaseColors(self) self.customAttributesWidget = CustomAttributes(self) self.emptyWidget = QWidget(self) self.stack.addWidget(self.baseColorsWidget) self.stack.addWidget(self.customAttributesWidget) self.stack.addWidget(self.emptyWidget) self.tree.currentItemChanged.connect(self.currentItemChanged) self.tree.setCurrentItem(self.baseColorsItem) self.scheme.currentChanged.connect(self.currentSchemeChanged) self.scheme.changed.connect(self.changed) self.baseColorsWidget.changed.connect(self.baseColorsChanged) self.customAttributesWidget.changed.connect(self.customAttributesChanged) self.fontChooser.currentFontChanged.connect(self.fontChanged) self.fontSize.valueChanged.connect(self.fontChanged) self.printScheme.clicked.connect(self.printSchemeChanged) app.translateUI(self) def translateUI(self): self.printScheme.setText(_("Use this scheme for printing")) self.fontLabel.setText(_("Font:")) self.baseColorsItem.setText(0, _("Base Colors")) self.defaultStylesItem.setText(0, _("Default Styles")) self.defaultStyleNames = defaultStyleNames() self.allStyleNames = allStyleNames() for name in textformats.defaultStyles: self.defaultStyles[name].setText(0, self.defaultStyleNames[name]) for group, styles in ly.colorize.default_mapping(): self.allStyles[group][0].setText(0, self.allStyleNames[group][0]) for name, base, clss in styles: self.allStyles[group][1][name].setText(0, self.allStyleNames[group][1][name]) def currentItemChanged(self, item, previous): if item is self.baseColorsItem: self.stack.setCurrentWidget(self.baseColorsWidget) elif not item.parent(): self.stack.setCurrentWidget(self.emptyWidget) else: data = self.data[self.scheme.currentScheme()] w = self.customAttributesWidget self.stack.setCurrentWidget(w) toptext = None if item.parent() is self.defaultStylesItem: # default style w.setTitle(item.text(0)) w.setTristate(False) w.setTextFormat(data.defaultStyles[item.name]) else: # specific style of specific group group, name = item.parent().group, item.name w.setTitle("{0}: {1}".format(item.parent().text(0), item.text(0))) inherit = item.base if inherit: toptext = _("(Inherits: {name})").format(name=self.defaultStyleNames[inherit]) w.setTristate(bool(inherit)) w.setTextFormat(data.allStyles[group][name]) w.setTopText(toptext) def currentSchemeChanged(self): scheme = self.scheme.currentScheme() if scheme not in self.data: self.data[scheme] = textformats.TextFormatData(scheme) self.updateDisplay() if self.tree.currentItem(): self.currentItemChanged(self.tree.currentItem(), None) with qutil.signalsBlocked(self.printScheme): self.printScheme.setChecked(scheme == self._printScheme) def fontChanged(self): data = self.data[self.scheme.currentScheme()] data.font = self.fontChooser.currentFont() data.font.setPointSizeF(self.fontSize.value()) self.updateDisplay() self.changed.emit() def printSchemeChanged(self): if self.printScheme.isChecked(): self._printScheme = self.scheme.currentScheme() else: self._printScheme = None self.changed.emit() def addSchemeData(self, scheme, tfd): self.data[scheme] = tfd def currentSchemeData(self): return self.data[self.scheme.currentScheme()] def updateDisplay(self): data = self.data[self.scheme.currentScheme()] with qutil.signalsBlocked(self.fontChooser, self.fontSize): self.fontChooser.setCurrentFont(data.font) self.fontSize.setValue(data.font.pointSizeF()) with qutil.signalsBlocked(self): # update base colors for name in textformats.baseColors: self.baseColorsWidget.color[name].setColor(data.baseColors[name]) # update base colors for whole treewidget p = QApplication.palette() p.setColor(QPalette.Base, data.baseColors['background']) p.setColor(QPalette.Text, data.baseColors['text']) p.setColor(QPalette.Highlight, data.baseColors['selectionbackground']) p.setColor(QPalette.HighlightedText, data.baseColors['selectiontext']) self.tree.setPalette(p) def setItemTextFormat(item, f): font = QFont(data.font) if f.hasProperty(QTextFormat.ForegroundBrush): item.setForeground(0, f.foreground().color()) else: item.setForeground(0, data.baseColors['text']) if f.hasProperty(QTextFormat.BackgroundBrush): item.setBackground(0, f.background().color()) else: item.setBackground(0, QBrush()) font.setWeight(f.fontWeight()) font.setItalic(f.fontItalic()) font.setUnderline(f.fontUnderline()) item.setFont(0, font) # update looks of default styles for name in textformats.defaultStyles: setItemTextFormat(self.defaultStyles[name], data.defaultStyles[name]) # update looks of all the specific styles for group, styles in ly.colorize.default_mapping(): children = self.allStyles[group][1] for name, inherit, clss in styles: f = QTextCharFormat(data.defaultStyles[inherit]) if inherit else QTextCharFormat() f.merge(data.allStyles[group][name]) setItemTextFormat(children[name], f) def baseColorsChanged(self, name): # keep data up to date with base colors data = self.data[self.scheme.currentScheme()] data.baseColors[name] = self.baseColorsWidget.color[name].color() self.updateDisplay() self.changed.emit() def customAttributesChanged(self): item = self.tree.currentItem() if not item or not item.parent(): return data = self.data[self.scheme.currentScheme()] if item.parent() is self.defaultStylesItem: # a default style has been changed data.defaultStyles[item.name] = self.customAttributesWidget.textFormat() else: # a specific style has been changed group, name = item.parent().group, item.name data.allStyles[group][name] = self.customAttributesWidget.textFormat() self.updateDisplay() self.changed.emit() def import_(self, filename): from . import import_export import_export.importTheme(filename, self, self.scheme) def export(self, name, filename): from . import import_export try: import_export.exportTheme(self, name, filename) except (IOError, OSError) as e: QMessageBox.critical(self, _("Error"), _( "Can't write to destination:\n\n{url}\n\n{error}").format( url=filename, error=e.strerror)) def loadSettings(self): self.data = {} # holds all data with scheme as key self._printScheme = QSettings().value("printer_scheme", "default", type("")) self.scheme.loadSettings("editor_scheme", "editor_schemes") def saveSettings(self): self.scheme.saveSettings("editor_scheme", "editor_schemes", "fontscolors") for scheme in self.scheme.schemes(): if scheme in self.data: self.data[scheme].save(scheme) if self._printScheme: QSettings().setValue("printer_scheme", self._printScheme) else: QSettings().remove("printer_scheme")
class mainwindow(QtGui.QMainWindow): '''主窗体''' def __init__(self): super(mainwindow, self).__init__() self.setWindowTitle('组件设计工具') self.setWindowIcon(QIcon(':/image/组件设计工具.png')) self.setMinimumWidth(1024) self.setMinimumHeight(800) self.showMaximized() self.menuBar().show() self.createMenus() #self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint) labelSizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) editSizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) cwVLayout = QVBoxLayout() cwHLayout = QHBoxLayout() lLayout = QVBoxLayout() rLayout = QVBoxLayout() self.lw = QListWidget() self.lw.setSelectionMode(QAbstractItemView.SingleSelection) lLayout.addWidget(self.lw) self.lw.itemSelectionChanged.connect(self.on_select) lGroup = QGroupBox('项目列表') lGroup.setLayout(lLayout) cwHLayout.addWidget(lGroup, 2) lGroup.setContentsMargins(0, 12, 0, 22) tLayout = QVBoxLayout() bLayout = QHBoxLayout() self.tGroup = QGroupBox('配置信息') self.bGroup = QGroupBox('生成代码') self.tGroup.setLayout(tLayout) self.tGroup.setEnabled(False) self.bGroup.setLayout(bLayout) self.bGroup.setEnabled(False) cwHLayout.addWidget(self.tGroup, 8) cwVLayout.addLayout(cwHLayout) cwVLayout.addWidget(self.bGroup) self.tw_config = QTreeWidget() headerLabels = QStringList() headerLabels.append(' 项目') headerLabels.append(' 值') self.tw_config.setHeaderLabels(headerLabels) self.tw_config.setColumnWidth(0, 312) self.tw_config.setColumnWidth(1, 660) thLayout = QHBoxLayout() thLayout.setContentsMargins(0, 6, 0, 0) thLayout.addSpacing(10) modify_btn = QPushButton('') #修改 modify_btn.setObjectName('modify_btn') modify_btn.clicked.connect(self.on_modify) del_btn = QPushButton('') #删除 del_btn.setObjectName('del_btn') del_btn.clicked.connect(self.on_del) thLayout.addWidget(modify_btn) thLayout.addWidget(del_btn) thLayout.addStretch(0) tLayout.addLayout(thLayout) tLayout.addWidget(self.tw_config) bhLayout = QHBoxLayout() lable1 = QLabel('工程名称:') lable1.setSizePolicy(labelSizePolicy) self.et_project_name = QLineEdit() self.et_project_name.setSizePolicy(editSizePolicy) bhLayout.addWidget(lable1) bhLayout.addWidget(self.et_project_name) bhLayout.addSpacing(16) lable2 = QLabel('工程位置:') lable2.setSizePolicy(labelSizePolicy) self.et_project_location = QLineEdit() self.et_project_location.setReadOnly(True) self.et_project_location.setSizePolicy(editSizePolicy) btn_location = QPushButton('') #打开 btn_location.setObjectName('btn_location') btn_location.setSizePolicy(labelSizePolicy) btn_location.clicked.connect(self.getProjectLocation) bhLayout.addWidget(lable2) bhLayout.addWidget(self.et_project_location) bhLayout.addSpacing(10) bhLayout.addWidget(btn_location) #bhLayout.addStretch(0) gen_btn = QPushButton('') # 生成 gen_btn.setObjectName('gen_btn') gen_btn.setSizePolicy(labelSizePolicy) gen_btn.clicked.connect(self.on_gen) bhLayout.addSpacing(45) bhLayout.addWidget(gen_btn) bLayout.addLayout(bhLayout) bLayout.setContentsMargins(10, 24, 22, 34) statusBar = self.statusBar() sBH = QHBoxLayout() copyright = QLabel('') copyright.setAlignment(QtCore.Qt.AlignCenter) copyright.setStyleSheet("color:#acacac") statusBar.setMinimumHeight(30) statusBar.addWidget(copyright, 10) cw = QWidget() cw.setLayout(cwVLayout) self.setCentralWidget(cw) self._initByConfig() self.setMinimumSize(400, 200) def _initByConfig(self): '''初始化''' pass def createMenus(self): '''创建菜单''' self.ToolBar = self.addToolBar('') self.ToolBar.setMinimumHeight(54) newBtn = QToolButton() newBtn.setText('创建项目') newBtn.setIcon(QIcon(':/image/创建项目.png')) newBtn.setToolButtonStyle(3) newBtn.setFixedWidth(99) OpenBtn = QToolButton() OpenBtn.setText('打开项目') OpenBtn.setIcon(QIcon(':/image/打开.png')) OpenBtn.setToolButtonStyle(3) OpenBtn.setFixedWidth(99) AboutBtn = QToolButton() AboutBtn.setText('关于') AboutBtn.setIcon(QIcon(':/image/关于.png')) AboutBtn.setToolButtonStyle(3) AboutBtn.setFixedWidth(99) HelpBtn = QToolButton() HelpBtn.setText('帮助') HelpBtn.setIcon(QIcon(':/image/帮助.png')) HelpBtn.setToolButtonStyle(3) HelpBtn.setFixedWidth(99) newBtn.clicked.connect(self.on_new) OpenBtn.clicked.connect(self.on_open) AboutBtn.clicked.connect(self.on_about) HelpBtn.clicked.connect(self.on_help) self.ToolBar.addWidget(newBtn) self.ToolBar.addWidget(OpenBtn) self.ToolBar.addWidget(AboutBtn) self.ToolBar.addWidget(HelpBtn) self.ToolBar.setMovable(False) self.ToolBar.setVisible(True) def on_help(self): app.g_pwd = os.getcwd() if not (QtGui.QDesktopServices.openUrl( QUrl.fromLocalFile(app.g_pwd + os.sep + 'image' + os.sep + 'help.pdf'))): print app.g_pwd + os.sep + '/image/help.pdf' QMessageBox.critical(None, "Failure", "Cannot open help manual") def on_about(self): abt = AboutDlg() abt.exec_() def on_new(self): '''新建向导''' app.g_configurations = Configuration() # 用来渲染的配置数据 dlg = wizard.MyWizard() if dlg.exec_(): app.g_configurations.initialized = True app.g_projects.append(app.g_configurations) content = app.g_configurations.toJson() self.path = QFileDialog.getSaveFileName( self, "选择模板保存的路径", app.g_pwd + os.sep + "configurations" + os.sep + app.g_configurations.project_name.encode('utf-8') + ".json", "Config (*.json)") fileInfo = QFileInfo(self.path) if not self.path.isEmpty(): path = app.QString2str(self.path) with open(path, 'w+') as f: f.write(content) self.addConfig(fileInfo.baseName(), fileInfo.filePath(), content) #self.lw.addItem(app.g_configurations.project_name) def getProjectLocation(self): '''获取项目路径''' path = QFileDialog.getExistingDirectory() path = QDir.fromNativeSeparators(path) self.et_project_location.setText(path) def on_open(self): '''打开现有配置''' fileName = QFileDialog.getOpenFileName( self, "选择现有模板", app.g_pwd + os.sep + "configurations", "Config (*.json)") if fileName.isEmpty(): return self.path = fileName with open(app.QString2str(fileName), 'r') as f: content = f.read() fileInfo = QFileInfo(fileName) if not fileInfo.exists(): return config = Configuration() config.fromJson(content) config.allone_dir = os.getenv('ALLONEDIR', '../..').replace('\\', '/') self.addConfig(fileInfo.baseName(), fileInfo.filePath(), content) self.on_select() def on_del(self): self.tw_config.clear() self.bGroup.setEnabled(False) self.tGroup.setEnabled(False) index = self.lw.currentRow() self.lw.takeItem(index) def on_select(self): '''选取配置''' item = self.lw.currentItem() if item != None: content = item.data(QtCore.Qt.UserRole).toString() config = Configuration() config.fromJson(app.QString2str(content)) self.currentConfig = config self.showConfigInfo(self.currentConfig) self.bGroup.setEnabled(True) self.path = item.data(QtCore.Qt.UserRole + 1).toString() # index = self.lw.currentRow() # if index < len(app.g_projects): # self.currentConfig = app.g_projects[index] # self.showConfigInfo(self.currentConfig) # self.bGroup.setEnabled(True) def addConfig(self, fileName, filePath, config): item = QListWidgetItem(fileName) item.setData(QtCore.Qt.UserRole, config) item.setData(QtCore.Qt.UserRole + 1, filePath) self.lw.addItem(item) self.lw.setCurrentRow(0) def showConfigInfo(self, cf): '''显示配置信息''' self.tw_config.clear() self.et_project_name.setText(cf.project_name) self.et_project_location.setText(cf.project_location) sr = QStringList() sr.append('信息') root1 = QTreeWidgetItem(sr) sr = QStringList() sr.append('Qt库') root2 = QTreeWidgetItem(sr) sr = QStringList() sr.append('模块') root3a = QTreeWidgetItem(sr) sr = QStringList() sr.append('第三方库') root3b = QTreeWidgetItem(sr) sr = QStringList() sr.append('接口') root4 = QTreeWidgetItem(sr) self.tw_config.addTopLevelItem(root1) self.tw_config.addTopLevelItem(root2) self.tw_config.addTopLevelItem(root3a) self.tw_config.addTopLevelItem(root3b) self.tw_config.addTopLevelItem(root4) sr1c00 = QStringList() sr1c00.append("项目名称") sr1c00.append(cf.project_name) r1c00 = QTreeWidgetItem(sr1c00) root1.addChild(r1c00) # sr1c0 = QStringList() # sr1c0.append("项目位置") # sr1c0.append(cf.project_location) # r1c0 = QTreeWidgetItem(sr1c0) # root1.addChild(r1c0) sr1c1 = QStringList() sr1c1.append("组件类型") sr1c1.append(cf.component_type) r1c1 = QTreeWidgetItem(sr1c1) root1.addChild(r1c1) sr1c2 = QStringList() sr1c2.append("源模板") sr1c2.append(cf.template_source) r1c2 = QTreeWidgetItem(sr1c2) root1.addChild(r1c2) sr1c3 = QStringList() sr1c3.append("平台类型") tmp_pt = "" if cf.platform_type & configuration.PT_WIN32: tmp_pt += "win32;" if cf.platform_type & configuration.PT_LINUX: tmp_pt += "linux" sr1c3.append(tmp_pt) r1c3 = QTreeWidgetItem(sr1c3) root1.addChild(r1c3) sr1c4 = QStringList() sr1c4.append("平台级别") sr1c4.append(cf.platform_version) r1c4 = QTreeWidgetItem(sr1c4) root1.addChild(r1c4) sr1c5 = QStringList() sr1c5.append("资源文件") if cf.resourcesFile == "True": sr1c5.append("添加") else: sr1c5.append("未添加") r1c5 = QTreeWidgetItem(sr1c5) root1.addChild(r1c5) sr1c6 = QStringList() sr1c6.append("翻译文件") if cf.translateFile == "True": sr1c6.append("添加") else: sr1c6.append("未添加") r1c6 = QTreeWidgetItem(sr1c6) root1.addChild(r1c6) for qt in cf.qt_libs: sr2 = QStringList() sr2.append(qt['name']) sr2.append(qt['qt']) r2 = QTreeWidgetItem(sr2) root2.addChild(r2) for module in cf.modules: sr3a = QStringList() sr3a.append(module['name']) sr3a.append(module['description']) r3a = QTreeWidgetItem(sr3a) root3a.addChild(r3a) # sr3b = QStringList() # sr3b.append('ALLONE_DIR') # sr3b.append(os.getenv('ALLONEDIR','../..')) # 第二个参数是默认值 # r3b = QTreeWidgetItem(sr3b) # root3b.addChild(r3b) for info in cf.thirdpart_lib: sr3b = QStringList() sr3b.append(info['libname']) sr3b.append(info['libpath']) r3b = QTreeWidgetItem(sr3b) root3b.addChild(r3b) for key in cf.interfaces.keys(): sr4 = QStringList() sr4.append(key) if cf.interfaces[key]: sr4.append('实现') else: sr4.append('未实现') r4 = QTreeWidgetItem(sr4) root4.addChild(r4) self.tw_config.expandAll() self.tw_config.header().resizeSection(0, 300) self.tGroup.setEnabled(True) def on_modify(self): '''修改配置''' if self.currentConfig: app.g_configurations = copy.copy(self.currentConfig) dlg = wizard.MyWizard() if dlg.exec_(): item = self.lw.currentItem() if item != None: content = app.g_configurations.toJson() item.setData(QtCore.Qt.UserRole, content) path = item.data(QtCore.Qt.UserRole + 1).toString() if not path.isEmpty(): path = app.QString2str(path) with open(path, 'w+') as f: f.write(content) self.on_select() def on_gen(self): '''生成工程''' if not self.currentConfig: return #获取工程名及有效路径 project_name = self.et_project_name.text() project_location = self.et_project_location.text() qdir = QDir(project_location) if not qdir.exists(): if not qdir.mkpath(project_location): QMessageBox.warning(self, '警告', '路径无效!') return project_location = qdir.absolutePath() if not project_location.endsWith( '/') and not project_location.endsWith('\\'): project_location += os.sep project_location.replace('\\', '/') if project_name.isEmpty() or project_location.isEmpty(): QMessageBox.warning(self, '警告', '项目名称或路径不能为空!') return self.currentConfig.project_name = app.QString2str(project_name) self.currentConfig.project_location = app.QString2str(project_location) content = self.currentConfig.toJson() fileInfo = QFileInfo(self.path) if not self.path.isEmpty(): path = app.QString2str(self.path) with open(path, 'w+') as f: f.write(content) item = self.lw.currentItem() item.setData(QtCore.Qt.UserRole, content) template_name = self.currentConfig.template_source template_dir = app.g_pwd + os.sep + 'templates' + os.sep + template_name.encode( 'utf-8') with open(template_dir + os.sep + 'config.json', 'r') as f: self.currentConfig.config_content = f.read() ret_json = app.render(self.currentConfig.config_content, config=self.currentConfig) self.currentConfig.config = json.loads(ret_json) for file in self.currentConfig.config['files']: sourcepath = template_dir + os.sep + file['source'].encode('utf-8') targetdir = self.currentConfig.project_location + self.currentConfig.project_name targetpath = targetdir + os.sep + file['target'] fi = QFileInfo(targetpath) qdir = fi.absoluteDir() if not qdir.exists(): qdir.mkpath(fi.absolutePath()) with open(sourcepath, 'r') as f: content = f.read() content = app.render(content, config=self.currentConfig) #渲染文件 with open(targetpath, 'w+') as f: f.write(content.encode('utf-8')) QMessageBox.information(self, '提示', '生成成功!')
class StackViewer(QWidget): " Implements the stack viewer for a debugger " def __init__(self, debugger, parent=None): QWidget.__init__(self, parent) self.__debugger = debugger self.currentStack = None self.currentFrame = 0 self.__createPopupMenu() self.__createLayout() if Settings().showStackViewer == False: self.__onShowHide(True) return def __createPopupMenu(self): " Creates the popup menu " self.__framesMenu = QMenu() self.__setCurrentMenuItem = self.__framesMenu.addAction( "Set current (single click)", self.__onSetCurrent) self.__jumpMenuItem = self.__framesMenu.addAction( "Set current and jump to the source (double click)", self.__onSetCurrentAndJump) return def __createLayout(self): " Creates the widget layout " verticalLayout = QVBoxLayout(self) verticalLayout.setContentsMargins(0, 0, 0, 0) verticalLayout.setSpacing(0) self.headerFrame = QFrame() self.headerFrame.setFrameStyle(QFrame.StyledPanel) self.headerFrame.setAutoFillBackground(True) headerPalette = self.headerFrame.palette() headerBackground = headerPalette.color(QPalette.Background) headerBackground.setRgb(min(headerBackground.red() + 30, 255), min(headerBackground.green() + 30, 255), min(headerBackground.blue() + 30, 255)) headerPalette.setColor(QPalette.Background, headerBackground) self.headerFrame.setPalette(headerPalette) self.headerFrame.setFixedHeight(24) self.__stackLabel = QLabel("Stack") expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding) fixedSpacer = QSpacerItem(3, 3) self.__showHideButton = QToolButton() self.__showHideButton.setAutoRaise(True) self.__showHideButton.setIcon(PixmapCache().getIcon('less.png')) self.__showHideButton.setFixedSize(20, 20) self.__showHideButton.setToolTip("Hide frames list") self.__showHideButton.setFocusPolicy(Qt.NoFocus) self.__showHideButton.clicked.connect(self.__onShowHide) headerLayout = QHBoxLayout() headerLayout.setContentsMargins(0, 0, 0, 0) headerLayout.addSpacerItem(fixedSpacer) headerLayout.addWidget(self.__stackLabel) headerLayout.addSpacerItem(expandingSpacer) headerLayout.addWidget(self.__showHideButton) self.headerFrame.setLayout(headerLayout) self.__framesList = QTreeWidget(self) self.__framesList.setSortingEnabled(False) # I might not need that because of two reasons: # - the window has no focus # - the window has custom current indicator # self.__framesList.setAlternatingRowColors( True ) self.__framesList.setRootIsDecorated(False) self.__framesList.setItemsExpandable(False) self.__framesList.setUniformRowHeights(True) self.__framesList.setSelectionMode(QAbstractItemView.NoSelection) self.__framesList.setSelectionBehavior(QAbstractItemView.SelectRows) self.__framesList.setItemDelegate(NoOutlineHeightDelegate(4)) self.__framesList.setFocusPolicy(Qt.NoFocus) self.__framesList.setContextMenuPolicy(Qt.CustomContextMenu) self.__framesList.itemClicked.connect(self.__onFrameClicked) self.__framesList.itemDoubleClicked.connect( self.__onFrameDoubleClicked) self.__framesList.customContextMenuRequested.connect( self.__showContextMenu) self.__framesList.setHeaderLabels( ["", "File:line", "Function", "Full path"]) verticalLayout.addWidget(self.headerFrame) verticalLayout.addWidget(self.__framesList) return def __onShowHide(self, startup=False): " Triggered when show/hide button is clicked " if startup or self.__framesList.isVisible(): self.__framesList.setVisible(False) self.__showHideButton.setIcon(PixmapCache().getIcon('more.png')) self.__showHideButton.setToolTip("Show frames list") self.__minH = self.minimumHeight() self.__maxH = self.maximumHeight() self.setMinimumHeight(self.headerFrame.height()) self.setMaximumHeight(self.headerFrame.height()) Settings().showStackViewer = False else: self.__framesList.setVisible(True) self.__showHideButton.setIcon(PixmapCache().getIcon('less.png')) self.__showHideButton.setToolTip("Hide frames list") self.setMinimumHeight(self.__minH) self.setMaximumHeight(self.__maxH) Settings().showStackViewer = True return def clear(self): " Clears the content " self.__framesList.clear() self.currentStack = None self.__stackLabel.setText("Stack") return def __resizeColumns(self): " Resize the files list columns " self.__framesList.header().setStretchLastSection(True) self.__framesList.header().resizeSections(QHeaderView.ResizeToContents) self.__framesList.header().resizeSection(0, 22) self.__framesList.header().setResizeMode(0, QHeaderView.Fixed) return def populate(self, stack): " Sets the new call stack and selects the first item in it " self.clear() self.currentStack = stack self.currentFrame = 0 frameNumber = 0 for s in stack: if len(s) == 2: # This is when an exception comes funcName = "" else: funcName = s[2] item = StackFrameItem(s[0], s[1], funcName, frameNumber) self.__framesList.addTopLevelItem(item) frameNumber += 1 self.__resizeColumns() self.__framesList.topLevelItem(0).setCurrent(True) self.__stackLabel.setText("Stack (total: " + str(len(stack)) + ")") return def getFrameNumber(self): " Provides the current frame number " return self.currentFrame def __onFrameClicked(self, item, column): " Triggered when a frame is clicked " if item.isCurrent(): return # Hide the current indicator self.__framesList.topLevelItem(self.currentFrame).setCurrent(False) # Show the new indicator self.currentFrame = item.getFrameNumber() for index in xrange(self.__framesList.topLevelItemCount()): item = self.__framesList.topLevelItem(index) if item.getFrameNumber() == self.currentFrame: item.setCurrent(True) self.__debugger.remoteClientVariables(1, self.currentFrame) # globals self.__debugger.remoteClientVariables(0, self.currentFrame) # locals return def __onFrameDoubleClicked(self, item, column): " Triggered when a frame is double clicked " # The frame has been switched already because the double click # signal always comes after the single click one fileName = item.getFilename() lineNumber = item.getLineNumber() editorsManager = GlobalData().mainWindow.editorsManager() editorsManager.openFile(fileName, lineNumber) editor = editorsManager.currentWidget().getEditor() editor.gotoLine(lineNumber) editorsManager.currentWidget().setFocus() return def __showContextMenu(self, coord): " Shows the frames list context menu " self.__contextItem = self.__framesList.itemAt(coord) if self.__contextItem is not None: self.__setCurrentMenuItem.setEnabled( not self.__contextItem.isCurrent()) self.__framesMenu.popup(QCursor.pos()) return def __onSetCurrent(self): " Context menu item handler " self.__onFrameClicked(self.__contextItem, 0) return def __onSetCurrentAndJump(self): " Context menu item handler " self.__onFrameClicked(self.__contextItem, 0) self.__onFrameDoubleClicked(self.__contextItem, 0) return def switchControl(self, isInIDE): " Switches the UI depending where the control flow is " self.__framesList.setEnabled(isInIDE) return
class MainWindow(QtGui.QMainWindow): """A configurable hex editor that supports binary templates and scripting through use of the construct library """ def __init__(self, file_name=None): """Initializer""" super(MainWindow, self).__init__() #Flag set to ignore the next data change event self._treeChangedData = False self._isUntitled = True self._curFile = '' self._setCurrentFile('') self.__mimeTypes = magic.Magic(mime=True) # UI attribute definitions (populated in __initUI and the various # __create* methods) #ToolBar self._fileToolBar = self.addToolBar("File") #StatusBar self._lbAddress = QtGui.QLabel() self._lbAddressName = QtGui.QLabel() self._lbSize = QtGui.QLabel() self._lbSizeName = QtGui.QLabel() self._lbOverwriteMode = QtGui.QLabel() self._lbOverwriteModeName = QtGui.QLabel() #Menus self._fileMenu = self.menuBar().addMenu("&File") self._editMenu = self.menuBar().addMenu("&Edit") self._helpMenu = self.menuBar().addMenu("&Help") #Action definitions self._openAct = None self._saveAct = None self._saveAsAct = None self._saveReadableAct = None self._saveSelReadableAct = None self._exitAct = None self._undoAct = None self._redoAct = None self._aboutAct = None self._optionsAct = None #Other self._hexEdit = QHexEdit() self._treeDissected = QTreeWidget() self._optionsDialog = OptionsDialog() self.__initUI() self.readSettings() # Create plugin manager # Which plugin types to load and which categories to put them in category_mapping = {"FormatDissectors": FormatDissector} self._manager = PluginManager(categories_filter=category_mapping) self._manager.setPluginPlaces(["plugins"]) #Dissectors self._dissector = None self._availDissectors = {} #load in the plugins self.__reloadPlugins() if file_name: self.loadFile(file_name) ############# # GUI SETUP # ############# def about(self): """Display an 'About' dialog box describing the application""" QtGui.QMessageBox.about(self, "About ParSlither", "Parslither v0.1 (WIP)") def closeEvent(self, event): # pylint: disable-msg=W0613 """(PyQT event handler) the application is due to close""" self.writeSettings() del self._optionsDialog self.close() def __createActions(self): """Create actions for the menus and toolbars in the UI""" self._openAct = QAction(QtGui.QIcon(':/images/open.png'), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.dlgOpen) self._saveAct = QAction(QtGui.QIcon(':/images/save.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self._saveAsAct = QAction("Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.dlgSaveAs) self._saveReadableAct = QAction("Save as &Readable...", self, statusTip="Save in a readable format", triggered=self.dlgSaveToReadableFile) self._saveSelReadableAct = QAction("Save Selection Readable...", self, statusTip="Save selection in a readable format", triggered=self.dlgSaveSelectionToReadableFile) self._exitAct = QAction("E&xit", self, shortcut="Ctrl+Q", statusTip="Exit the application", triggered=self.close) self._undoAct = QAction("&Undo", self, shortcut=QKeySequence.Undo, triggered=self._hexEdit.undo) self._redoAct = QAction("&Redo", self, shortcut=QKeySequence.Redo, triggered=self._hexEdit.redo) self._aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) self._optionsAct = QAction("&Options", self, statusTip="Show the options dialog", triggered=self.showOptionsDialog) def __initMenus(self): """Initialize menus for the UI""" self._fileMenu.addAction(self._openAct) self._fileMenu.addAction(self._saveAct) self._fileMenu.addAction(self._saveAsAct) self._fileMenu.addAction(self._saveReadableAct) self._fileMenu.addSeparator() self._fileMenu.addAction(self._exitAct) self._editMenu.addAction(self._undoAct) self._editMenu.addAction(self._redoAct) self._editMenu.addAction(self._saveSelReadableAct) self._editMenu.addSeparator() self._editMenu.addAction(self._optionsAct) self._helpMenu.addAction(self._aboutAct) def __initStatusBar(self): """Initialize status bar for the UI""" # Address Label self._lbAddressName.setText("Address:") self.statusBar().addPermanentWidget(self._lbAddressName) self._lbAddress.setFrameShape(QtGui.QFrame.Panel) self._lbAddress.setFrameShadow(QtGui.QFrame.Sunken) self._lbAddress.setMinimumWidth(70) self.statusBar().addPermanentWidget(self._lbAddress) self._hexEdit.currentAddressChanged.connect(self.__setAddress) # Address Size self._lbSizeName.setText("Size:") self.statusBar().addPermanentWidget(self._lbSizeName) self._lbSize.setFrameShape(QtGui.QFrame.Panel) self._lbSize.setFrameShadow(QtGui.QFrame.Sunken) self._lbSize.setMinimumWidth(70) self.statusBar().addPermanentWidget(self._lbSize) self._hexEdit.currentSizeChanged.connect(self.__setSize) # Overwrite Mode label self._lbOverwriteModeName.setText("Mode:") self.statusBar().addPermanentWidget(self._lbOverwriteModeName) self._lbOverwriteMode.setFrameShape(QtGui.QFrame.Panel) self._lbOverwriteMode.setFrameShadow(QtGui.QFrame.Sunken) self._lbOverwriteMode.setMinimumWidth(70) self.statusBar().addPermanentWidget(self._lbOverwriteMode) self.setOverwriteMode(self._hexEdit.overwriteMode()) self.statusBar().showMessage("Ready") def __initToolBars(self): """Initialize ToolBars for the UI""" self._fileToolBar.addAction(self._openAct) self._fileToolBar.addAction(self._saveAct) def __initDockWindows(self): """Initialize Docked Windows for the UI""" dock = QtGui.QDockWidget("Dissected", self) dock.setFeatures( QDockWidget.DockWidgetFeatures(QDockWidget.NoDockWidgetFeatures)) dock.setAllowedAreas(Qt.Qt.BottomDockWidgetArea) dock.setWidget(self._treeDissected) self.addDockWidget(Qt.Qt.BottomDockWidgetArea, dock) def __initUI(self): """Initialize everything for the UI""" self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self._optionsDialog.accepted.connect(self.__optionsAccepted) self._hexEdit.overwriteModeChanged.connect(self.setOverwriteMode) self._hexEdit.dataChanged.connect(self.__hexDataChanged) self.setCentralWidget(self._hexEdit) #we don't want to be able to sort by rows (keep serialized order) self._treeDissected.setSortingEnabled(False) tree_header = QTreeWidgetItem(["Name", "Value"]) self._treeDissected.setHeaderItem(tree_header) self.__createActions() self.__initMenus() self.__initToolBars() self.__initStatusBar() self.__initDockWindows() ########### # PLUGINS # ########### def __reloadPlugins(self): """ Load plugins """ self._manager.locatePlugins() self._manager.loadPlugins() self.__refreshDissectors() def __refreshDissectors(self): """Refresh dissectors from the plugin manager""" self._availDissectors = {} for plugin in self._manager.getPluginsOfCategory("FormatDissectors"): # plugin.plugin_object is an instance of the plugin plug_obj = plugin.plugin_object self._availDissectors[plug_obj.name] = plug_obj # if we have a dissector loaded, reload it from the dict of # available dissectors if self._dissector and self._dissector.name in self._availDissectors: self._dissector = self._availDissectors[self._dissector.name] else: self._dissector = None ############ # SETTINGS # ############ def readSettings(self): """Reload all settings for this application from storage""" settings = QtCore.QSettings() pos = settings.value('pos', QtCore.QPoint(200, 200)).toPoint() size = settings.value('size', QtCore.QSize(610, 460)).toSize() self.move(pos) self.resize(size) editor = self._hexEdit editor.setAddressArea(settings.value("AddressArea").toBool()) editor.setAsciiArea(settings.value("AsciiArea").toBool()) editor.setHighlighting(settings.value("Highlighting").toBool()) editor.setOverwriteMode(settings.value("OverwriteMode").toBool()) editor.setReadOnly(settings.value("ReadOnly").toBool()) editor.setHighlightingColor(QColor(settings.value("HighlightingColor"))) editor.setAddressAreaColor(QColor(settings.value("AddressAreaColor"))) editor.setSelectionColor(QColor(settings.value("SelectionColor"))) default_font = QFont("Courier New", 10) editor.setFont(QFont(settings.value("WidgetFont", default_font))) editor.setAddressWidth(settings.value("AddressAreaWidth").toInt()[0]) def writeSettings(self): """Write all non-session settings to storage""" settings = QtCore.QSettings() settings.setValue('pos', self.pos()) settings.setValue('size', self.size()) def showOptionsDialog(self): """Show the options dialog""" self._optionsDialog.show() def __optionsAccepted(self): """(Callback) The user is ok with the changes to the settings""" self.writeSettings() self.readSettings() ######################### # FILE LOADING / SAVING # ######################### def save(self): """Save the entire hex editor buffer to a file as-is If a file was already open, it will be saved to that file, otherwise a file chooser will be presented and the user will be asked to choose a file """ def write_whole(handle): handle.write(self._hexEdit.data()) if self._isUntitled: return self.dlgSaveAs() else: return self.writeFile(write_whole, self._curFile, as_is=True) def dlgSaveAs(self): """Save the entire hex editor buffer to a file as-is""" def write_whole(handle): handle.write(self._hexEdit.data()) return self.writeFile(write_whole, as_is=True, op_name="Save As") def dlgSaveToReadableFile(self): """Save the entire hex editor buffer to a file in a readable format""" def write_readable(handle): handle.write(self._hexEdit.toReadableString()) return self.writeFile(write_readable, op_name="Save To Readable File") def dlgSaveSelectionToReadableFile(self): """Save the selected section to a file in a readable format""" def write_sel_readable(handle): handle.write(self._hexEdit.toReadableString()) return self.writeFile(write_sel_readable, op_name="Save To Readable File") def writeFile(self, write_func, file_name=None, as_is=False, op_name=""): """Try to save content to the specified file using the specified write_func Arguments: write_func(handle) -- Function to save the desired content to the file Keyword Arguments: file_name -- Filename to save to instead of displaying a file picker (Defaults to None) as_is -- whether the hex editor is being saved without modification (Defaults to False) op_name -- (Defaults to "") """ if not file_name: file_name = QtGui.QFileDialog.getSaveFileName(self, op_name, self._curFile) if not file_name: return False file_handle = QtCore.QFile(file_name) if not file_handle.open(QtCore.QFile.WriteOnly): error_msg = "Cannot write file %s:\n%s." % \ (file_name, file_handle.errorString()) QtGui.QMessageBox.warning(self, "HexEdit", error_msg) return False # call the function to actually write to the file write_func(file_handle) # only set the current file to the saved filename if we're # saving the whole file as-is if as_is: self._setCurrentFile(file_name) self.statusBar().showMessage("File saved", 2000) return True def dlgOpen(self): """Display a file picker and ask the user to choose a file to open in the hex editor""" file_name = QtGui.QFileDialog.getOpenFileName(self) if file_name: self.loadFile(file_name) def loadFile(self, file_name): """Load the specified file into the hex editor""" file_handle = QtCore.QFile(file_name) if not file_handle.open( QtCore.QFile.ReadOnly): warning_msg = "Cannot read file %s:\n%s." % \ file_name, file_handle.errorString() QtGui.QMessageBox.warning(self, "QHexEdit", warning_msg) return QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) self._hexEdit.setData(file_handle.readAll()) QtGui.QApplication.restoreOverrideCursor() self._setCurrentFile(file_name) self.statusBar().showMessage("File loaded", 2000) self.__autoLoadDissector(file_name) self.__refreshDissectionTree() def _setCurrentFile(self, file_name): """Set the current filename""" self._curFile = file_name self._isUntitled = (file_name == "") self.setWindowModified(False) window_title = "%s[*] - QHexEdit" % \ QtCore.QFileInfo(self._curFile).fileName() self.setWindowTitle(window_title) def __setAddress(self, address): """Set the address at the caret""" self._lbAddress.setText('%x' % address) def setOverwriteMode(self, mode): """Overwrite the nibble following the caret instead of inserting?""" if mode: self._lbOverwriteMode.setText("Overwrite") else: self._lbOverwriteMode.setText("Insert") def __setSize(self, size): """Set the total size of the file in the hex editor""" self._lbSize.setText('%d' % size) def __hexDataChanged(self): """The data in the hex editor control changed""" # don't refresh the dissection tree if the hex editor data was # based on the data in there anyways if not self._treeChangedData: self.__refreshDissectionTree() self._treeChangedData = False def __autoLoadDissector(self, file_name): """Try to auto-assign an available dissector based on filename and mimetype """ #don't use a dissector if we can't auto-assign one self._dissector = None #first try and assign a dissector by extension for dissector in self._availDissectors.values(): for extension in dissector.file_exts: if file_name.endsWith(extension): self._dissector = dissector return #now try to assign a dissector by mimetype file_mimetype = self.__mimeTypes.from_file(file_name) if not file_mimetype: return for dissector in self._availDissectors.values(): for supp_mimetype in dissector.file_mimetypes: if file_name == supp_mimetype: self._dissector = dissector return def __refreshDissectionTree(self): """Refresh the tree of dissected data with data from the hex editor""" self._treeDissected.clear() #only refresh if we have data and a dissector if self._dissector and self._hexEdit.data(): self.__addToDissectionTree( self._dissector.dissect(self._hexEdit.data().data())) def __addToDissectionTree(self, attr_container, parent=None): """Recursively add a Construct container and its children to the dissected data tree widget Arguments: attr_container -- Construct container whose attributes to recursively add to the tree Keyword Arguments: parent -- Reference to the tree item that represents the current container (default None) """ def add_item_to_tree(child): """ Add a tree item to the tree, with its parent item as the parent if it has one """ if not parent: self._treeDissected.addTopLevelItem(child) else: parent.addChild(child) def add_container_to_tree(name, source_container): """ Add a container to the dissection tree as a tree item and handle its children """ container_item = QTreeWidgetItem([name, ""]) add_item_to_tree(container_item) self.__addToDissectionTree(source_container, container_item) #look through the container's attributes and add them to the tree #as necessary for attr_k in attr_container: #skip private attributes if we were given any if not attr_k.startswith("_"): #get the value of this attribute attr_v = attr_container[attr_k] #value is a container if isinstance(attr_v, construct.Container): add_container_to_tree(attr_k, attr_v) #value is list-like elif isinstance(attr_v, (list, tuple)): elem_idx = 0 for elem in attr_v: elem_name = "%s[%d]" % (attr_k, elem_idx) #list element is a container if isinstance(elem, construct.Container): add_container_to_tree(elem_name, elem) #list element is a primitive or non-construct object else: new_item = QTreeWidgetItem([elem_name, str(elem)]) add_item_to_tree(new_item) elem_idx += 1 #value is a primitive or a non-construct object else: add_item_to_tree(QTreeWidgetItem([attr_k, str(attr_v)]))
class DBDatabasesWidget(QWidget): """Displays a list of Databases""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.db = None self.setWindowTitle("Databases") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setHeaderLabels(["Server", "User", ""]) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(False) self.tree.setColumnWidth(C.widget, 20) self.connect(self.tree, SIGNAL('itemSelectionChanged()'), self.on_tree_selection_changed) self.connect(self.tree, SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'), self.on_tree_double_clicked) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def on_open_server(self, butt): self.emit(SIGNAL("open_server"), butt.property("server").toString()) def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.server, srv['server']) item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.widget, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers()
def __addSimilarity(self, similarity, titleText): " Adds a similarity " # Label title = QLabel(titleText) title.setFont(self.__headerFont) self.__vLayout.addWidget(title) self.__widgets.append(title) # List of files simTable = QTreeWidget(self.bodyWidget) simTable.setAlternatingRowColors(True) simTable.setRootIsDecorated(False) simTable.setItemsExpandable(False) simTable.setSortingEnabled(False) simTable.setItemDelegate(NoOutlineHeightDelegate(4)) simTable.setUniformRowHeights(True) simTable.itemActivated.connect(self.__similarityActivated) simTable.setHeaderLabels(["File name", "Line"]) for item in similarity.files: values = [item[0], str(item[1])] simTable.addTopLevelItem(QTreeWidgetItem(values)) # Resizing simTable.header().resizeSections(QHeaderView.ResizeToContents) simTable.header().setStretchLastSection(True) # Height self.__setTableHeight(simTable) self.__vLayout.addWidget(simTable) self.__widgets.append(simTable) # The fragment itself if len(similarity.fragment) > 10: # Take first 9 lines text = "\n".join(similarity.fragment[:9]) + "\n ..." toolTip = "\n".join(similarity.fragment) else: text = "\n".join(similarity.fragment) toolTip = "" fragmentLabel = QLabel("<pre>" + self.__htmlEncode(text) + "</pre>") if toolTip != "": fragmentLabel.setToolTip("<pre>" + self.__htmlEncode(toolTip) + "</pre>") palette = fragmentLabel.palette() palette.setColor(QPalette.Background, QColor(250, 250, 175)) palette.setColor(QPalette.Foreground, QColor(0, 0, 0)) fragmentLabel.setPalette(palette) fragmentLabel.setFrameShape(QFrame.StyledPanel) fragmentLabel.setAutoFillBackground(True) labelFont = fragmentLabel.font() labelFont.setFamily(GlobalData().skin.baseMonoFontFace) fragmentLabel.setFont(labelFont) self.__vLayout.addWidget(fragmentLabel) self.__widgets.append(fragmentLabel) return
class RecentProjectsViewer( QWidget ): " Recent projects viewer implementation " def __init__( self, parent = None ): QWidget.__init__( self, parent ) self.__projectContextItem = None self.__fileContextItem = None self.upper = self.__createRecentFilesLayout() self.lower = self.__createRecentProjectsLayout() self.__createProjectPopupMenu() self.__createFilePopupMenu() layout = QVBoxLayout() layout.setContentsMargins( 1, 1, 1, 1 ) splitter = QSplitter( Qt.Vertical ) splitter.addWidget( self.upper ) splitter.addWidget( self.lower ) splitter.setCollapsible( 0, False ) splitter.setCollapsible( 1, False ) layout.addWidget( splitter ) self.setLayout( layout ) self.__populateProjects() self.__populateFiles() self.__updateProjectToolbarButtons() self.__updateFileToolbarButtons() # Debugging mode support self.__debugMode = False parent.debugModeChanged.connect( self.__onDebugMode ) return def setTooltips( self, switchOn ): " Switches the tooltips mode " for index in xrange( 0, self.recentFilesView.topLevelItemCount() ): self.recentFilesView.topLevelItem( index ).updateIconAndTooltip() for index in xrange( 0, self.projectsView.topLevelItemCount() ): self.projectsView.topLevelItem( index ).updateTooltip() return def __createFilePopupMenu( self ): " create the recent files popup menu " self.__fileMenu = QMenu( self.recentFilesView ) self.__openMenuItem = self.__fileMenu.addAction( \ PixmapCache().getIcon( 'openitem.png' ), 'Open', self.__openFile ) self.__copyPathFileMenuItem = self.__fileMenu.addAction( \ PixmapCache().getIcon( 'copytoclipboard.png' ), 'Copy path to clipboard', self.__filePathToClipboard ) self.__fileMenu.addSeparator() self.__delFileMenuItem = self.__fileMenu.addAction( \ PixmapCache().getIcon( 'trash.png' ), 'Delete from recent', self.__deleteFile ) self.recentFilesView.setContextMenuPolicy( Qt.CustomContextMenu ) self.connect( self.recentFilesView, SIGNAL( "customContextMenuRequested(const QPoint &)" ), self.__handleShowFileContextMenu ) self.connect( GlobalData().project, SIGNAL( 'recentFilesChanged' ), self.__populateFiles ) return def __createProjectPopupMenu( self ): " Creates the recent project popup menu " self.__projectMenu = QMenu( self.projectsView ) self.__prjLoadMenuItem = self.__projectMenu.addAction( \ PixmapCache().getIcon( 'load.png' ), 'Load', self.__loadProject ) self.__projectMenu.addSeparator() self.__propsMenuItem = self.__projectMenu.addAction( \ PixmapCache().getIcon( 'smalli.png' ), 'Properties', self.__viewProperties ) self.__prjCopyPathMenuItem = self.__projectMenu.addAction( \ PixmapCache().getIcon( 'copytoclipboard.png' ), 'Copy path to clipboard', self.__prjPathToClipboard ) self.__projectMenu.addSeparator() self.__delPrjMenuItem = self.__projectMenu.addAction( \ PixmapCache().getIcon( 'trash.png' ), 'Delete from recent', self.__deleteProject ) self.projectsView.setContextMenuPolicy( Qt.CustomContextMenu ) self.connect( self.projectsView, SIGNAL( "customContextMenuRequested(const QPoint &)" ), self.__handleShowPrjContextMenu ) self.connect( Settings().iInstance, SIGNAL( 'recentListChanged' ), self.__populateProjects ) GlobalData().project.projectChanged.connect( self.__projectChanged ) return def __createRecentFilesLayout( self ): " Creates the upper part - recent files " headerFrame = QFrame() headerFrame.setFrameStyle( QFrame.StyledPanel ) headerFrame.setAutoFillBackground( True ) headerPalette = headerFrame.palette() headerBackground = headerPalette.color( QPalette.Background ) headerBackground.setRgb( min( headerBackground.red() + 30, 255 ), min( headerBackground.green() + 30, 255 ), min( headerBackground.blue() + 30, 255 ) ) headerPalette.setColor( QPalette.Background, headerBackground ) headerFrame.setPalette( headerPalette ) headerFrame.setFixedHeight( 24 ) recentFilesLabel = QLabel() recentFilesLabel.setText( "Recent files" ) headerLayout = QHBoxLayout() headerLayout.setContentsMargins( 3, 0, 0, 0 ) headerLayout.addWidget( recentFilesLabel ) headerFrame.setLayout( headerLayout ) self.recentFilesView = QTreeWidget() self.recentFilesView.setAlternatingRowColors( True ) self.recentFilesView.setRootIsDecorated( False ) self.recentFilesView.setItemsExpandable( False ) self.recentFilesView.setSortingEnabled( True ) self.recentFilesView.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.recentFilesView.setUniformRowHeights( True ) self.__filesHeaderItem = QTreeWidgetItem( [ "", "File", "Absolute path" ] ) self.recentFilesView.setHeaderItem( self.__filesHeaderItem ) self.recentFilesView.header().setSortIndicator( 1, Qt.AscendingOrder ) self.connect( self.recentFilesView, SIGNAL( "itemSelectionChanged()" ), self.__fileSelectionChanged ) self.connect( self.recentFilesView, SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ), self.__fileActivated ) # Toolbar part - buttons self.openFileButton = QAction( PixmapCache().getIcon( 'openitem.png' ), 'Open the highlighted file', self ) self.connect( self.openFileButton, SIGNAL( "triggered()" ), self.__openFile ) self.copyFilePathButton = QAction( \ PixmapCache().getIcon( 'copytoclipboard.png' ), 'Copy path to clipboard', self ) self.connect( self.copyFilePathButton, SIGNAL( "triggered()" ), self.__filePathToClipboard ) spacer = QWidget() spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.trashFileButton = QAction( PixmapCache().getIcon( 'delitem.png' ), 'Remove selected (not from the disk)', self ) self.connect( self.trashFileButton, SIGNAL( "triggered()" ), self.__deleteFile ) self.upperToolbar = QToolBar() self.upperToolbar.setMovable( False ) self.upperToolbar.setAllowedAreas( Qt.TopToolBarArea ) self.upperToolbar.setIconSize( QSize( 16, 16 ) ) self.upperToolbar.setFixedHeight( 28 ) self.upperToolbar.setContentsMargins( 0, 0, 0, 0 ) self.upperToolbar.addAction( self.openFileButton ) self.upperToolbar.addAction( self.copyFilePathButton ) self.upperToolbar.addWidget( spacer ) self.upperToolbar.addAction( self.trashFileButton ) recentFilesLayout = QVBoxLayout() recentFilesLayout.setContentsMargins( 0, 0, 0, 0 ) recentFilesLayout.setSpacing( 0 ) recentFilesLayout.addWidget( headerFrame ) recentFilesLayout.addWidget( self.upperToolbar ) recentFilesLayout.addWidget( self.recentFilesView ) upperContainer = QWidget() upperContainer.setContentsMargins( 0, 0, 0, 0 ) upperContainer.setLayout( recentFilesLayout ) return upperContainer def getRecentFilesToolbar( self ): " Provides a reference to the recent files toolbar " return self.upperToolbar def __createRecentProjectsLayout( self ): " Creates the bottom layout " self.headerFrame = QFrame() self.headerFrame.setFrameStyle( QFrame.StyledPanel ) self.headerFrame.setAutoFillBackground( True ) headerPalette = self.headerFrame.palette() headerBackground = headerPalette.color( QPalette.Background ) headerBackground.setRgb( min( headerBackground.red() + 30, 255 ), min( headerBackground.green() + 30, 255 ), min( headerBackground.blue() + 30, 255 ) ) headerPalette.setColor( QPalette.Background, headerBackground ) self.headerFrame.setPalette( headerPalette ) self.headerFrame.setFixedHeight( 24 ) recentProjectsLabel = QLabel() recentProjectsLabel.setText( "Recent projects" ) expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding ) self.__showHideButton = QToolButton() self.__showHideButton.setAutoRaise( True ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideButton.setFixedSize( 20, 20 ) self.__showHideButton.setToolTip( "Hide recent projects list" ) self.__showHideButton.setFocusPolicy( Qt.NoFocus ) self.connect( self.__showHideButton, SIGNAL( 'clicked()' ), self.__onShowHide ) headerLayout = QHBoxLayout() headerLayout.setContentsMargins( 3, 0, 0, 0 ) headerLayout.addWidget( recentProjectsLabel ) headerLayout.addSpacerItem( expandingSpacer ) headerLayout.addWidget( self.__showHideButton ) self.headerFrame.setLayout( headerLayout ) # Toolbar part - buttons self.loadButton = QAction( PixmapCache().getIcon( 'load.png' ), 'Load the highlighted project', self ) self.connect( self.loadButton, SIGNAL( "triggered()" ), self.__loadProject ) self.propertiesButton = QAction( PixmapCache().getIcon( 'smalli.png' ), 'Show the highlighted project ' \ 'properties', self ) self.connect( self.propertiesButton, SIGNAL( "triggered()" ), self.__viewProperties ) self.copyPrjPathButton = QAction( \ PixmapCache().getIcon( 'copytoclipboard.png' ), 'Copy path to clipboard', self ) self.connect( self.copyPrjPathButton, SIGNAL( "triggered()" ), self.__prjPathToClipboard ) spacer = QWidget() spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.trashButton = QAction( PixmapCache().getIcon( 'delitem.png' ), 'Remove selected (not from the disk)', self ) self.connect( self.trashButton, SIGNAL( "triggered()" ), self.__deleteProject ) self.lowerToolbar = QToolBar() self.lowerToolbar.setMovable( False ) self.lowerToolbar.setAllowedAreas( Qt.TopToolBarArea ) self.lowerToolbar.setIconSize( QSize( 16, 16 ) ) self.lowerToolbar.setFixedHeight( 28 ) self.lowerToolbar.setContentsMargins( 0, 0, 0, 0 ) self.lowerToolbar.addAction( self.loadButton ) self.lowerToolbar.addAction( self.propertiesButton ) self.lowerToolbar.addAction( self.copyPrjPathButton ) self.lowerToolbar.addWidget( spacer ) self.lowerToolbar.addAction( self.trashButton ) self.projectsView = QTreeWidget() self.projectsView.setAlternatingRowColors( True ) self.projectsView.setRootIsDecorated( False ) self.projectsView.setItemsExpandable( False ) self.projectsView.setSortingEnabled( True ) self.projectsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.projectsView.setUniformRowHeights( True ) self.__projectsHeaderItem = QTreeWidgetItem( [ "", "Project", "Absolute path" ] ) self.projectsView.setHeaderItem( self.__projectsHeaderItem ) self.projectsView.header().setSortIndicator( 1, Qt.AscendingOrder ) self.connect( self.projectsView, SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ), self.__projectActivated ) self.connect( self.projectsView, SIGNAL( "itemSelectionChanged()" ), self.__projectSelectionChanged ) recentProjectsLayout = QVBoxLayout() recentProjectsLayout.setContentsMargins( 0, 0, 0, 0 ) recentProjectsLayout.setSpacing( 0 ) recentProjectsLayout.addWidget( self.headerFrame ) recentProjectsLayout.addWidget( self.lowerToolbar ) recentProjectsLayout.addWidget( self.projectsView ) lowerContainer = QWidget() lowerContainer.setContentsMargins( 0, 0, 0, 0 ) lowerContainer.setLayout( recentProjectsLayout ) return lowerContainer def getRecentProjectsToolbar( self ): " Provides a reference to the projects toolbar " return self.lowerToolbar def __projectSelectionChanged( self ): " Handles the projects changed selection " selected = list( self.projectsView.selectedItems() ) if selected: self.__projectContextItem = selected[ 0 ] else: self.__projectContextItem = None self.__updateProjectToolbarButtons() return def __fileSelectionChanged( self ): " Handles the files changed selection " selected = list( self.recentFilesView.selectedItems() ) if selected: self.__fileContextItem = selected[ 0 ] else: self.__fileContextItem = None self.__updateFileToolbarButtons() return def __updateProjectToolbarButtons( self ): " Updates the toolbar buttons depending on the __projectContextItem " if self.__projectContextItem is None: self.loadButton.setEnabled( False ) self.propertiesButton.setEnabled( False ) self.copyPrjPathButton.setEnabled( False ) self.trashButton.setEnabled( False ) else: enabled = self.__projectContextItem.isValid() isCurrentProject = self.__projectContextItem.isCurrent() self.propertiesButton.setEnabled( enabled ) self.copyPrjPathButton.setEnabled( True ) self.loadButton.setEnabled( enabled and not isCurrentProject and not self.__debugMode ) self.trashButton.setEnabled( not isCurrentProject ) return def __updateFileToolbarButtons( self ): " Updates the toolbar buttons depending on the __fileContextItem " enabled = self.__fileContextItem is not None self.openFileButton.setEnabled( enabled ) self.copyFilePathButton.setEnabled( enabled ) self.trashFileButton.setEnabled( enabled ) return def __handleShowPrjContextMenu( self, coord ): " Show the project item context menu " self.__projectContextItem = self.projectsView.itemAt( coord ) if self.__projectContextItem is None: return enabled = self.__projectContextItem.isValid() isCurrentProject = self.__projectContextItem.isCurrent() self.__propsMenuItem.setEnabled( enabled ) self.__delPrjMenuItem.setEnabled( not isCurrentProject ) # fName = self.__projectContextItem.getFilename() self.__prjLoadMenuItem.setEnabled( enabled and \ not isCurrentProject and \ not self.__debugMode ) self.__projectMenu.popup( QCursor.pos() ) return def __sortProjects( self ): " Sort the project items " self.projectsView.sortItems( \ self.projectsView.sortColumn(), self.projectsView.header().sortIndicatorOrder() ) return def __sortFiles( self ): " Sort the file items " self.recentFilesView.sortItems( \ self.recentFilesView.sortColumn(), self.recentFilesView.header().sortIndicatorOrder() ) return def __resizeProjectColumns( self ): """ Resize the projects list columns """ self.projectsView.header().setStretchLastSection( True ) self.projectsView.header().resizeSections( \ QHeaderView.ResizeToContents ) self.projectsView.header().resizeSection( 0, 22 ) self.projectsView.header().setResizeMode( 0, QHeaderView.Fixed ) return def __resizeFileColumns( self ): " Resize the files list columns " self.recentFilesView.header().setStretchLastSection( True ) self.recentFilesView.header().resizeSections( \ QHeaderView.ResizeToContents ) self.recentFilesView.header().resizeSection( 0, 22 ) self.recentFilesView.header().setResizeMode( 0, QHeaderView.Fixed ) return def __projectActivated( self, item, column ): " Handles the double click (or Enter) on the item " self.__projectContextItem = item self.__loadProject() return def __fileActivated( self, item, column ): " Handles the double click (or Enter) on a file item " self.__fileContextItem = item self.__openFile() return def __viewProperties( self ): " Handles the 'view properties' context menu item " if self.__projectContextItem is None: return if not self.__projectContextItem.isValid(): return if self.__projectContextItem.isCurrent(): # This is the current project - it can be edited project = GlobalData().project dialog = ProjectPropertiesDialog( project ) if dialog.exec_() == QDialog.Accepted: importDirs = [] for index in xrange( dialog.importDirList.count() ): importDirs.append( dialog.importDirList.item( index ).text() ) scriptName = dialog.scriptEdit.text().strip() relativePath = relpath( scriptName, project.getProjectDir() ) if not relativePath.startswith( '..' ): scriptName = relativePath project.updateProperties( scriptName, importDirs, dialog.creationDateEdit.text().strip(), dialog.authorEdit.text().strip(), dialog.licenseEdit.text().strip(), dialog.copyrightEdit.text().strip(), dialog.versionEdit.text().strip(), dialog.emailEdit.text().strip(), dialog.descriptionEdit.toPlainText().strip() ) else: # This is not the current project - it can be viewed fName = self.__projectContextItem.getFilename() dialog = ProjectPropertiesDialog( fName ) dialog.exec_() return def __deleteProject( self ): " Handles the 'delete from recent' context menu item " if self.__projectContextItem is None: return # Removal from the visible list is done via a signal which comes back # from settings fName = self.__projectContextItem.getFilename() Settings().deleteRecentProject( fName ) return def __loadProject( self ): " handles 'Load' context menu item " if self.__projectContextItem is None: return if not self.__projectContextItem.isValid(): return if self.__debugMode: return projectFileName = self.__projectContextItem.getFilename() if self.__projectContextItem.isCurrent(): GlobalData().mainWindow.openFile( projectFileName, -1 ) return # This is the current project, open for text editing QApplication.processEvents() QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) ) if os.path.exists( projectFileName ): mainWin = GlobalData().mainWindow editorsManager = mainWin.editorsManagerWidget.editorsManager if editorsManager.closeRequest(): prj = GlobalData().project prj.setTabsStatus( editorsManager.getTabsStatus() ) editorsManager.closeAll() prj.loadProject( projectFileName ) mainWin.activateProjectTab() else: logging.error( "The project " + \ os.path.basename( projectFileName ) + \ " disappeared from the file system." ) self.__populateProjects() QApplication.restoreOverrideCursor() return def __populateProjects( self ): " Populates the recent projects " self.projectsView.clear() for item in Settings().recentProjects: self.projectsView.addTopLevelItem( RecentProjectViewItem( item ) ) self.__sortProjects() self.__resizeProjectColumns() self.__updateProjectToolbarButtons() return def __populateFiles( self ): " Populates the recent files " self.recentFilesView.clear() for path in GlobalData().project.recentFiles: self.recentFilesView.addTopLevelItem( RecentFileViewItem( path ) ) self.__sortFiles() self.__resizeFileColumns() self.__updateFileToolbarButtons() return def __projectChanged( self, what ): " Triggered when the current project is changed " if what == CodimensionProject.CompleteProject: self.__populateProjects() self.__populateFiles() return if what == CodimensionProject.Properties: # Update the corresponding tooltip items = self.projectsView.findItems( GlobalData().project.fileName, Qt.MatchExactly, 2 ) if len( items ) != 1: logging.error( "Unexpected number of matched projects: " + \ str( len( items ) ) ) return items[ 0 ].updateTooltip() return def __openFile( self ): " Handles 'open' file menu item " self.__fileContextItem.updateIconAndTooltip() fName = self.__fileContextItem.getFilename() if not self.__fileContextItem.isValid(): logging.warning( "Cannot open " + fName ) return fileType = detectFileType( fName ) if fileType == PixmapFileType: GlobalData().mainWindow.openPixmapFile( fName ) return GlobalData().mainWindow.openFile( fName, -1 ) return def __deleteFile( self ): " Handles 'delete from recent' file menu item " self.removeRecentFile( self.__fileContextItem.getFilename() ) return def __handleShowFileContextMenu( self, coord ): " File context menu " self.__fileContextItem = self.recentFilesView.itemAt( coord ) if self.__fileContextItem is not None: self.__fileMenu.popup( QCursor.pos() ) return def __filePathToClipboard( self ): " Copies the file item path to the clipboard " if self.__fileContextItem is not None: QApplication.clipboard().setText( \ self.__fileContextItem.getFilename() ) return def __prjPathToClipboard( self ): " Copies the project item path to the clipboard " if self.__projectContextItem is not None: QApplication.clipboard().setText( \ self.__projectContextItem.getFilename() ) return def onFileUpdated( self, fileName, uuid ): " Triggered when the file is updated: python or project " realPath = os.path.realpath( fileName ) count = self.recentFilesView.topLevelItemCount() for index in xrange( 0, count ): item = self.recentFilesView.topLevelItem( index ) itemRealPath = os.path.realpath( item.getFilename() ) if realPath == itemRealPath: item.updateIconAndTooltip() break for index in xrange( 0, self.projectsView.topLevelItemCount() ): item = self.projectsView.topLevelItem( index ) itemRealPath = os.path.realpath( item.getFilename() ) if realPath == itemRealPath: item.updateTooltip() break return def __onShowHide( self ): " Triggered when show/hide button is clicked " if self.projectsView.isVisible(): self.projectsView.setVisible( False ) self.lowerToolbar.setVisible( False ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'more.png' ) ) self.__showHideButton.setToolTip( "Show recent projects list" ) self.__minH = self.lower.minimumHeight() self.__maxH = self.lower.maximumHeight() self.lower.setMinimumHeight( self.headerFrame.height() ) self.lower.setMaximumHeight( self.headerFrame.height() ) else: self.projectsView.setVisible( True ) self.lowerToolbar.setVisible( True ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideButton.setToolTip( "Hide recent projects list" ) self.lower.setMinimumHeight( self.__minH ) self.lower.setMaximumHeight( self.__maxH ) return def __onDebugMode( self, newState ): " Triggered when debug mode has changed " self.__debugMode = newState # Disable the load project button self.__updateProjectToolbarButtons() return def removeRecentFile( self, fName ): " Removes a single file from the recent files list " GlobalData().project.removeRecentFile( fName ) for index in xrange( self.recentFilesView.topLevelItemCount() ): candidate = self.recentFilesView.topLevelItem( index ) if candidate.getFilename() == fName: self.recentFilesView.takeTopLevelItem( index ) return return
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.scriptPath, self.scriptArgs = "", [] self.profilerPath, self.tempPath = profilerPath, tempPath self.output = " ERROR: FAIL: No output ! " self.process = QProcess() self.process.finished.connect(self.on_process_finished) self.process.error.connect(self.on_process_error) self.tabWidget, self.stat = QTabWidget(), QWidget() self.tabWidget.tabCloseRequested.connect(lambda: self.tabWidget.setTabPosition(1) if self.tabWidget.tabPosition() == 0 else self.tabWidget.setTabPosition(0)) self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}') self.tabWidget.setMovable(True) self.tabWidget.setTabsClosable(True) self.vboxlayout1 = QVBoxLayout(self.stat) self.hboxlayout1 = QHBoxLayout() self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat) self.hboxlayout1.addWidget(self.filterTableLabel) self.filterTableLineEdit = QLineEdit(self.stat) self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ') self.hboxlayout1.addWidget(self.filterTableLineEdit) self.filterHintTableLabel = QLabel(" ? ", self.stat) self.hboxlayout1.addWidget(self.filterHintTableLabel) self.vboxlayout1.addLayout(self.hboxlayout1) self.tableWidget = QTableWidget(self.stat) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setColumnCount(8) self.tableWidget.setRowCount(2) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(1, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(2, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(3, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(4, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(5, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(6, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(7, item) self.tableWidget.itemDoubleClicked.connect( self.on_tableWidget_itemDoubleClicked) self.vboxlayout1.addWidget(self.tableWidget) self.tabWidget.addTab(self.stat, " ? ") self.source = QWidget() self.gridlayout = QGridLayout(self.source) self.scintillaWarningLabel = QLabel( "QScintilla is not installed!. Falling back to basic text edit!.", self.source) self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2) self.sourceTreeWidget = QTreeWidget(self.source) self.sourceTreeWidget.setAlternatingRowColors(True) self.sourceTreeWidget.itemActivated.connect( self.on_sourceTreeWidget_itemActivated) self.sourceTreeWidget.itemClicked.connect( self.on_sourceTreeWidget_itemClicked) self.sourceTreeWidget.itemDoubleClicked.connect( self.on_sourceTreeWidget_itemClicked) self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1) self.sourceTextEdit = QTextEdit(self.source) self.sourceTextEdit.setReadOnly(True) self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1) self.tabWidget.addTab(self.source, " ? ") self.result = QWidget() self.vlayout = QVBoxLayout(self.result) self.globalStatGroupBox = QGroupBox(self.result) self.hboxlayout = QHBoxLayout(self.globalStatGroupBox) self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox) self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.totalTimeLcdNumber.setNumDigits(7) self.totalTimeLcdNumber.display(1000000) self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel) self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.totalTimeLcdNumber) self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>", self.globalStatGroupBox) self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.tTimeLabel) self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.numCallLcdNumber.setNumDigits(7) self.numCallLcdNumber.display(1000000) self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.numCallLcdNumber) self.numCallLabel = QLabel("<b>Number of calls</b>", self.globalStatGroupBox) self.numCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.numCallLabel) self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.primCallLcdNumber.setNumDigits(7) self.primCallLcdNumber.display(1000000) self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.primCallLcdNumber) self.primCallLabel = QLabel("<b>Primitive calls (%)</b>", self.globalStatGroupBox) self.primCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.primCallLabel) self.vlayout.addWidget(self.globalStatGroupBox) try: from PyKDE4.kdeui import KRatingWidget self.rating = KRatingWidget(self.globalStatGroupBox) self.rating.setToolTip('Profiling Performance Rating') except ImportError: pass self.tabWidget.addTab(self.result, " Get Results ! ") self.resgraph = QWidget() self.vlayout2 = QVBoxLayout(self.result) self.graphz = QGroupBox(self.resgraph) self.hboxlayout2 = QHBoxLayout(self.graphz) try: from PyKDE4.kdeui import KLed KLed(self.graphz) except ImportError: pass self.hboxlayout2.addWidget(QLabel(''' Work in Progress :) Not Ready Yet''')) self.vlayout2.addWidget(self.graphz) self.tabWidget.addTab(self.resgraph, " Graphs and Charts ") self.pathz = QWidget() self.vlayout3 = QVBoxLayout(self.pathz) self.patz = QGroupBox(self.pathz) self.hboxlayout3 = QVBoxLayout(self.patz) self.profilepath = QLineEdit(profilerPath) self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open') self.getprofile.setToolTip('Dont touch if you dont know what are doing') self.getprofile.clicked.connect(lambda: self.profilepath.setText(str( QFileDialog.getOpenFileName(self.patz, ' Open the profile.py file ', path.expanduser("~"), ';;(profile.py)')))) self.hboxlayout3.addWidget(QLabel( '<center><b>Profile.py Python Library Full Path:</b></center>')) self.hboxlayout3.addWidget(self.profilepath) self.hboxlayout3.addWidget(self.getprofile) self.argGroupBox = QGroupBox(self.pathz) self.hbxlayout = QHBoxLayout(self.argGroupBox) self.argLineEdit = QLineEdit(self.argGroupBox) self.argLineEdit.setToolTip('Not touch if you dont know what are doing') self.argLineEdit.setPlaceholderText( 'Dont touch if you dont know what are doing') self.hbxlayout.addWidget(QLabel('<b>Additional Profile Arguments:</b>')) self.hbxlayout.addWidget(self.argLineEdit) self.hboxlayout3.addWidget(self.argGroupBox) self.vlayout3.addWidget(self.patz) self.tabWidget.addTab(self.pathz, " Paths and Configs ") self.outp = QWidget() self.vlayout4 = QVBoxLayout(self.outp) self.outgro = QGroupBox(self.outp) self.outgro.setTitle(" MultiProcessing Output Logs ") self.hboxlayout4 = QVBoxLayout(self.outgro) self.outputlog = QTextEdit() self.outputlog.setText(''' I do not fear computers, I fear the lack of them. -Isaac Asimov ''') self.hboxlayout4.addWidget(self.outputlog) self.vlayout4.addWidget(self.outgro) self.tabWidget.addTab(self.outp, " Logs ") self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"), 'New Profiling', self) self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"), 'Open Profiling', self) self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean', self) self.actionClean.triggered.connect(lambda: self.clearContent) self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About', self) self.actionAbout.triggered.connect(lambda: QMessageBox.about(self.dock, __doc__, ', '.join((__doc__, __license__, __author__, __email__)))) self.actionSave_profile = QAction(QIcon.fromTheme("document-save"), 'Save Profiling', self) self.actionManual = QAction(QIcon.fromTheme("help-contents"), 'Help', self) self.actionManual.triggered.connect(lambda: open_new_tab('http://docs.python.org/library/profile.html')) self.tabWidget.setCurrentIndex(2) self.globalStatGroupBox.setTitle("Global Statistics") item = self.tableWidget.horizontalHeaderItem(0) item.setText("Number of Calls") item = self.tableWidget.horizontalHeaderItem(1) item.setText("Total Time") item = self.tableWidget.horizontalHeaderItem(2) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(3) item.setText("Cumulative Time") item = self.tableWidget.horizontalHeaderItem(4) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(5) item.setText("Filename") item = self.tableWidget.horizontalHeaderItem(6) item.setText("Line") item = self.tableWidget.horizontalHeaderItem(7) item.setText("Function") self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat), "Statistics per Function") self.sourceTreeWidget.headerItem().setText(0, "Source files") self.tabWidget.setTabText(self.tabWidget.indexOf(self.source), "Sources Navigator") ####################################################################### self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(self.tabWidget) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) QToolBar(self.dock).addActions((self.actionNew_profiling, self.actionClean, self.actionSave_profile, self.actionLoad_profile, self.actionManual, self.actionAbout)) self.actionNew_profiling.triggered.connect( self.on_actionNew_profiling_triggered) self.actionLoad_profile.triggered.connect( self.on_actionLoad_profile_triggered) self.actionSave_profile.triggered.connect( self.on_actionSave_profile_triggered) self.locator.get_service('misc').add_widget(self.dock, QIcon.fromTheme("document-open-recent"), __doc__) if QSCI: # Scintilla source editor management self.scintillaWarningLabel.setText(' QScintilla is Ready ! ') layout = self.source.layout() layout.removeWidget(self.sourceTextEdit) self.sourceTextEdit = Qsci.QsciScintilla(self.source) layout.addWidget(self.sourceTextEdit, 0, 1) doc = self.sourceTextEdit doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit)) doc.setReadOnly(True) doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine) doc.setEdgeColumn(80) doc.setEdgeColor(QColor("#FF0000")) doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle) doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch) doc.setCaretLineVisible(True) doc.setMarginLineNumbers(1, True) doc.setMarginWidth(1, 25) doc.setTabWidth(4) doc.setEolMode(Qsci.QsciScintilla.EolUnix) self.marker = {} for color in COLORS: mnr = doc.markerDefine(Qsci.QsciScintilla.Background) doc.setMarkerBackgroundColor(color, mnr) self.marker[color] = mnr self.currentSourcePath = None # Connect table and tree filter edit signal to unique slot self.filterTableLineEdit.textEdited.connect( self.on_filterLineEdit_textEdited) # Timer to display filter hint message self.filterHintTimer = QTimer(self) self.filterHintTimer.setSingleShot(True) self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout) # Timer to start search self.filterSearchTimer = QTimer(self) self.filterSearchTimer.setSingleShot(True) self.filterSearchTimer.timeout.connect( self.on_filterSearchTimer_timeout) self.tabLoaded = {} for i in range(10): self.tabLoaded[i] = False self.backgroundTreeMatchedItems = {} self.resizeWidgetToContent(self.tableWidget) def on_actionNew_profiling_triggered(self): self.clearContent() self.scriptPath = str(QFileDialog.getOpenFileName(self.dock, "Choose your script to profile", path.expanduser("~"), "Python (*.py *.pyw)")) commandLine = [self.profilerPath, "-o", self.tempPath, self.scriptPath] + self.scriptArgs commandLine = " ".join(commandLine) ##if self.termCheckBox.checkState() == Qt.Checked: #termList = ["xterm", "aterm"] #for term in termList: #termPath = which(term) #if termPath: #break #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \ #% (termPath, commandLine) self.process.start(commandLine) if not self.process.waitForStarted(): print((" ERROR: {} failed!".format(commandLine))) return def on_process_finished(self, exitStatus): ' whan the process end ' print((" INFO: OK: QProcess is %s" % self.process.exitCode())) self.output = self.process.readAll().data() if not self.output: self.output = " ERROR: FAIL: No output ! " self.outputlog.setText(self.output + str(self.process.exitCode())) if path.exists(self.tempPath): self.setStat(self.tempPath) remove(self.tempPath) else: self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.") self.tabWidget.setCurrentIndex(2) def on_process_error(self, error): ' when the process fail, I hope you never see this ' print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ") if error == QProcess.FailedToStart: self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ") elif error == QProcess.Crashed: self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ") else: self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ") def on_actionLoad_profile_triggered(self): """Load a previous profile sessions""" statPath = str(QFileDialog.getOpenFileName(self.dock, "Open profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: self.clearContent() print(' INFO: OK: Loading profiling from ' + statPath) self.setStat(statPath) def on_actionSave_profile_triggered(self): """Save a profile sessions""" statPath = str(QFileDialog.getSaveFileName(self.dock, "Save profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: #TODO: handle error case and give feelback to user print(' INFO: OK: Saving profiling to ' + statPath) self.stat.save(statPath) #=======================================================================# # Common parts # #=======================================================================# def on_tabWidget_currentChanged(self, index): """slot for tab change""" # Kill search and hint timer if running to avoid cross effect for timer in (self.filterHintTimer, self.filterSearchTimer): if timer.isActive(): timer.stop() if not self.stat: #No stat loaded, nothing to do return self.populateTable() self.populateSource() def on_filterLineEdit_textEdited(self, text): """slot for filter change (table or tree""" if self.filterSearchTimer.isActive(): # Already runnning, stop it self.filterSearchTimer.stop() # Start timer self.filterSearchTimer.start(300) def on_filterHintTimer_timeout(self): """Timeout to warn user about text length""" print("timeout") tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: label = self.filterHintTableLabel label.setText("Type > 2 characters to search") def on_filterSearchTimer_timeout(self): """timeout to start search""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: text = self.filterTableLineEdit.text() label = self.filterHintTableLabel edit = self.filterTableLineEdit widget = self.tableWidget else: print("Unknow tab for filterSearch timeout !") print(("do search for %s" % text)) if not len(text): # Empty keyword, just clean all if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") self.warnUSer(True, edit) self.clearSearch() return if len(text) < 2: # Don't filter if text is too short and tell it to user self.filterHintTimer.start(600) return else: if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") # Search self.clearSearch() matchedItems = [] if tab == TAB_FUNCTIONSTAT: # Find items matchedItems = widget.findItems(text, Qt.MatchContains) widget.setSortingEnabled(False) matchedRows = [item.row() for item in matchedItems] # Hide matched items header = widget.verticalHeader() for row in range(widget.rowCount()): if row not in matchedRows: header.hideSection(row) widget.setSortingEnabled(True) else: print(" Unknow tab for filterSearch timeout ! ") print(("got %s members" % len(matchedItems))) self.warnUSer(matchedItems, edit) self.resizeWidgetToContent(widget) def resizeWidgetToContent(self, widget): """Resize all columns according to content""" for i in range(widget.columnCount()): widget.resizeColumnToContents(i) def clearSearch(self): """Clean search result For table, show all items For tree, remove colored items""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: header = self.tableWidget.verticalHeader() if header.hiddenSectionCount(): for i in range(header.count()): if header.isSectionHidden(i): header.showSection(i) def clearContent(self): # Clear tabs self.tableWidget.clearContents() self.sourceTreeWidget.clear() # Reset LCD numbers for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber, self.primCallLcdNumber): lcdNumber.display(1000000) # Reset stat self.pstat = None # Disable save as menu self.actionSave_profile.setEnabled(False) # Mark all tabs as unloaded for i in range(10): self.tabLoaded[i] = False def warnUSer(self, result, inputWidget): palette = inputWidget.palette() if result: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 255, 255)) else: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 136, 138)) inputWidget.setPalette(palette) inputWidget.update() def setStat(self, statPath): self.stat = Stat(path=statPath) # Global stat update self.totalTimeLcdNumber.display(self.stat.getTotalTime()) self.numCallLcdNumber.display(self.stat.getCallNumber()) self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio()) # Refresh current tab self.on_tabWidget_currentChanged(self.tabWidget.currentIndex()) # Activate save as menu self.actionSave_profile.setEnabled(True) try: self.rating.setMaxRating(10) self.rating.setRating( int(self.stat.getPrimitiveCallRatio()) / 10 - 1) except: pass #========================================================================# # Statistics table # #=======================================================================# def populateTable(self): row = 0 rowCount = self.stat.getStatNumber() progress = QProgressDialog("Populating statistics table...", "Abort", 0, 2 * rowCount) self.tableWidget.setSortingEnabled(False) self.tableWidget.setRowCount(rowCount) progress.setWindowModality(Qt.WindowModal) for (key, value) in self.stat.getStatItems(): #ncalls item = StatTableWidgetItem(str(value[0])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_NCALLS, item) colorTableItem(item, self.stat.getCallNumber(), value[0]) #total time item = StatTableWidgetItem(str(value[2])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[2]) #per call (total time) if value[0] != 0: tPerCall = str(value[2] / value[0]) cPerCall = str(value[3] / value[0]) else: tPerCall = "" cPerCall = "" item = StatTableWidgetItem(tPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TPERCALL, item) colorTableItem(item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), tPerCall) #per call (cumulative time) item = StatTableWidgetItem(cPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CPERCALL, item) colorTableItem(item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), cPerCall) #cumulative time item = StatTableWidgetItem(str(value[3])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[3]) #Filename self.tableWidget.setItem(row, STAT_FILENAME, StatTableWidgetItem(str(key[0]))) #Line item = StatTableWidgetItem(str(key[1])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_LINE, item) #Function name self.tableWidget.setItem(row, STAT_FUNCTION, StatTableWidgetItem(str(key[2]))) row += 1 # Store it in stat hash array self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT) progress.setValue(row) if progress.wasCanceled(): return for i in range(self.tableWidget.rowCount()): progress.setValue(row + i) for j in range(self.tableWidget.columnCount()): item = self.tableWidget.item(i, j) if item: item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setSortingEnabled(True) self.resizeWidgetToContent(self.tableWidget) progress.setValue(2 * rowCount) def on_tableWidget_itemDoubleClicked(self, item): matchedItems = [] filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text()) if not filename or filename.startswith("<"): # No source code associated, return immediatly return function = self.tableWidget.item(item.row(), STAT_FUNCTION).text() line = self.tableWidget.item(item.row(), STAT_LINE).text() self.on_tabWidget_currentChanged(TAB_SOURCE) # load source tab function = "%s (%s)" % (function, line) fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains, SOURCE_FILENAME) print(("find %s father" % len(fathers))) for father in fathers: findItems(father, function, SOURCE_FILENAME, matchedItems) print(("find %s items" % len(matchedItems))) if matchedItems: self.tabWidget.setCurrentIndex(TAB_SOURCE) self.sourceTreeWidget.scrollToItem(matchedItems[0]) self.on_sourceTreeWidget_itemClicked(matchedItems[0], SOURCE_FILENAME) matchedItems[0].setSelected(True) else: print("oups, item found but cannot scroll to it !") #=======================================================================# # Source explorer # #=====================================================================# def populateSource(self): items = {} for stat in self.stat.getStatKeys(): source = stat[0] function = "%s (%s)" % (stat[2], stat[1]) if source in ("", "profile") or source.startswith("<"): continue # Create the function child child = QTreeWidgetItem([function]) # Store it in stat hash array self.stat.setStatLink(child, stat, TAB_SOURCE) if source in items: father = items[source] else: # Create the father father = QTreeWidgetItem([source]) items[source] = father father.addChild(child) self.sourceTreeWidget.setSortingEnabled(False) for value in list(items.values()): self.sourceTreeWidget.addTopLevelItem(value) self.sourceTreeWidget.setSortingEnabled(True) def on_sourceTreeWidget_itemActivated(self, item, column): self.on_sourceTreeWidget_itemClicked(item, column) def on_sourceTreeWidget_itemClicked(self, item, column): line = 0 parent = item.parent() if QSCI: doc = self.sourceTextEdit if parent: pathz = parent.text(column) result = match("(.*) \(([0-9]+)\)", item.text(column)) if result: try: function = str(result.group(1)) line = int(result.group(2)) except ValueError: # We got garbage... falling back to line 0 pass else: pathz = item.text(column) pathz = path.abspath(str(pathz)) if self.currentSourcePath != pathz: # Need to load source self.currentSourcePath == pathz try: if QSCI: doc.clear() doc.insert(file(pathz).read()) else: self.sourceTextEdit.setPlainText(file(pathz).read()) except IOError: QMessageBox.warning(self, "Error", "Source file could not be found", QMessageBox.Ok) return if QSCI: for function, line in [(i[2], i[1] ) for i in self.stat.getStatKeys() if i[0] == pathz]: # expr, regexp, case sensitive, whole word, wrap, forward doc.findFirst("def", False, True, True, False, True, line, 0, True) end, foo = doc.getCursorPosition() time = self.stat.getStatTotalTime((pathz, line, function)) colorSource(doc, self.stat.getTotalTime(), time, line, end, self.marker) if QSCI: doc.ensureLineVisible(line)
class LibrarySearchDialog(QtGui.QDialog): def __init__(self, ms, parent=None): QtGui.QDialog.__init__(self, parent) settings = QSettings() size = settings.value("MainWindow/Size", QVariant(QSize(1024, 600))).toSize() self.resize(size) self.setWindowTitle( 'Identify unknown compound by mass spectra Library') self.ms = ms pms = processMS(ms) self.axis = pms[0] self.mass = pms[1] self.peak_MS = pms[2] self.maxmass = int(self.axis[-1]) self.initControls() self.initPlots() self.selectedIndex = [] self.percent = [] self._cpointsPicker1 = Qwt.QwtPicker(self.plot1.canvas()) self._cpointsPicker1.setSelectionFlags(Qwt.QwtPicker.PointSelection) self._cpointsPicker1.widgetMouseDoubleClickEvent = self.plot1MouseDoubleClickEvent def updatePlots(self): reply = QtGui.QMessageBox.question( self, 'EleComp Parameters', "Are you sure to Use Single Mass %s?" % self.selected_mz, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: # print self.x self.ElemCompDialog1() # self.m.setLabel(self.text1) # self.m.setValue(self.x, 0.0) # rowMs=int((self.x-self.scan_acquisition_time.data[0])/0.2) # self.showMs(rowMs) # self.plot1.replot() def plot1MouseDoubleClickEvent(self, event): self.xp = self.plot1.invTransform(Qwt.QwtPlot.xBottom, event.x()) n1 = np.searchsorted(self.axis, self.xp - 1) n2 = np.searchsorted(self.axis, self.xp + 1) self.selected_mz = self.axis[np.argmax(self.mass[n1:n2]) + n1] print self.xp print self.selected_mz self.updatePlots() def ElemCompDialog1(self): dialog = ElemCompDialog(mz=self.axis, mass=self.mass, xp=self.selected_mz) dialog.move(QPoint(100, 10)) res = dialog.exec_() def initControls(self): self.plot3 = Qwt.QwtPlot(self) self.plot3.setCanvasBackground(Qt.white) self.plot3.enableAxis(Qwt.QwtPlot.yLeft, False) self.plot3.enableAxis(Qwt.QwtPlot.xBottom, False) self.plot1 = Qwt.QwtPlot(self) self.plot1.setCanvasBackground(Qt.white) self.plot2 = Qwt.QwtPlot(self) self.plot2.setCanvasBackground(Qt.white) library_label = QLabel("MS in mass spectra Library:") self.library_list = QTreeWidget() self.library_list.setColumnCount(3) self.library_list.setHeaderLabels( ['No.', 'Similarity', 'Mol Wt', 'Formula', 'Name']) self.library_list.setSortingEnabled(False) self.connect(self.library_list, SIGNAL("itemSelectionChanged()"), self.libraryListClicked) self.connect(self.library_list, SIGNAL("itemActivated (QTreeWidgetItem *,int)"), self.libraryListDoubleClicked) mxiture_label = QLabel("Molecular structure :") # self.mixture_list = QListWidget() okButton = QPushButton("&Search") self.connect(okButton, SIGNAL("clicked()"), self.Seach) left_vbox = QVBoxLayout() left_vbox.addWidget(self.plot1) left_vbox.addWidget(self.plot2) right_vbox = QVBoxLayout() right_vbox.addWidget(library_label) right_vbox.addWidget(self.library_list) hboxPercent = QHBoxLayout() # hboxPercent.addWidget(percent_label) # hboxPercent.addWidget(self.edit_percent) right_vbox.addLayout(hboxPercent) # right_vbox.addWidget(self.add_button) right_vbox.addWidget(mxiture_label) right_vbox.addWidget(self.plot3) right_vbox.addWidget(okButton) hbox = QHBoxLayout() hbox.addLayout(left_vbox, 2.5) hbox.addLayout(right_vbox, 1.5) self.setLayout(hbox) #self.setCentralWidget(self.main_frame) def initPlots(self): self.plot3.clear() self.plot3.setAxisScale(self.plot1.xBottom, -4, 4) self.plot3.setAxisScale(self.plot1.yLeft, -4, 4) self.plot1.clear() self.plot1.setTitle("Search MS") self.plot1.setAxisTitle(Qwt.QwtPlot.yLeft, 'Intensity') grid = Qwt.QwtPlotGrid() pen = QPen(Qt.DotLine) pen.setColor(Qt.black) pen.setWidth(0) grid.setPen(pen) grid.attach(self.plot1) self.plot1.setAxisScale(self.plot1.yLeft, 0, 1.1 * np.max(self.mass)) color = QColor('black') curve = Qwt.QwtPlotCurve("test1") pen = QPen(color) pen.setWidth(1) curve.setPen(pen) #self.axis= np.arange(len(self.mass)) curve.setData(self.axis, self.mass) curve.setStyle(Qwt.QwtPlotCurve.Sticks) curve.attach(self.plot1) for i in range(len(self.peak_MS)): text_MS = Qwt.QwtText('%s' % (str(self.peak_MS[i][0]))) marker_MS = Qwt.QwtPlotMarker() marker_MS.setLabelAlignment(Qt.AlignCenter | Qt.AlignTop) marker_MS.setLabel(text_MS) marker_MS.setValue(self.peak_MS[i][0], self.peak_MS[i][1]) marker_MS.attach(self.plot1) self.plot1.replot() self.plot2.clear() self.plot2.setTitle("NIST MS") # self.plot2.setAxisTitle(Qwt.QwtPlot.xBottom, 'Raman shift (cm-1)') self.plot2.setAxisTitle(Qwt.QwtPlot.yLeft, 'Intensity') grid = Qwt.QwtPlotGrid() pen = QPen(Qt.DotLine) pen.setColor(Qt.black) pen.setWidth(0) grid.setPen(pen) grid.attach(self.plot2) self.plot2.replot() def libraryListClicked(self): row = self.library_list.indexOfTopLevelItem( self.library_list.currentItem()) self.row1 = self.masscor[row][0] print 'row: %s' % self.row1 self.showMs(self.row1) def libraryListDoubleClicked(self, item, pos): dialog = NistLibraryDialog(num=self.row1) dialog.move(QPoint(100, 10)) res = dialog.exec_() def showMs(self, row1): self.row1 = row1 self.cur.execute( "select name,peakindex,peakintensity from catalog where id=%d" % row1) temp = self.cur.fetchall() masstemp = np.frombuffer(temp[0][1], dtype=np.int) intensitytemp = np.frombuffer(temp[0][2], dtype=np.int) intensitytemp = 100 * intensitytemp / np.max(intensitytemp) row = np.zeros(len(masstemp)) mass = coo_matrix((intensitytemp, (row, masstemp)), shape=(1, ceil(masstemp[-1]) + 1)).todense() self.massSeacher = mass.tolist() radio_MS = 0.01 * (np.max(self.massSeacher[0]) - np.min(self.massSeacher[0])) peak_MS = [] for i in range(5, len(self.massSeacher[0]) - 5): if (self.massSeacher[0][i] == max(self.massSeacher[0][i - 5:i + 5]) and self.massSeacher[0][i] >= radio_MS): peak_intensity_MS = (i, self.massSeacher[0][i]) peak_MS.append(peak_intensity_MS) self.plot2.clear() self.plot2.setTitle("MS of %s" % str(temp[0][0][:-2])) color = QColor('black') curve2 = Qwt.QwtPlotCurve("test1") pen = QPen(color) pen.setWidth(1) curve2.setPen(pen) self.axis2 = masstemp curve2.setData(masstemp, intensitytemp) curve2.setStyle(Qwt.QwtPlotCurve.Sticks) curve2.attach(self.plot2) for i in range(len(peak_MS)): text_MS = Qwt.QwtText('%s' % (str(peak_MS[i][0]))) marker_MS = Qwt.QwtPlotMarker() marker_MS.setLabelAlignment(Qt.AlignCenter | Qt.AlignTop) marker_MS.setLabel(text_MS) marker_MS.setValue(peak_MS[i][0], peak_MS[i][1]) marker_MS.attach(self.plot2) x = np.hstack((self.axis, self.axis2)) x_min = np.min(x) x_max = np.max(x) y1_max = np.max(self.mass) y1_min = np.min(self.mass) y2_max = np.max(intensitytemp) y2_min = np.min(intensitytemp) self.plot1.setAxisScale(self.plot1.xBottom, 0, x_max * 1.1) self.plot2.setAxisScale(self.plot1.xBottom, 0, x_max * 1.1) self.plot1.setAxisScale(self.plot1.yLeft, 0, y1_max * 1.1) self.plot2.setAxisScale(self.plot1.yLeft, 0, y2_max * 1.1) self.plot1.replot() self.plot2.replot() self.ShowMolFile() def comnum(self): i = 0 for x in self.findms: if x in self.basems: i = i + 1 cor = i * 2.0 / (len(self.findms) + len(self.basems)) return cor def Seach_ZDJ(self): self.findms = [] (mz_bin, val_bin, peaks_bin) = processMS(binMS(self.ms)) peaks_bin.sort(key=lambda d: d[1], reverse=True) self.peak_index = [] self.peak_inten = [] for i in range(0, len(peaks_bin)): self.peak_index.append(int(peaks_bin[i][0])) self.peak_inten.append(peaks_bin[i][1]) if len(peaks_bin) < 10: self.findms = self.peak_index else: self.findms = self.peak_index[0:10] time0 = time.time() db = sqlite3.connect(NIST_DBPath) self.cur = db.cursor() self.cur.execute( "select id,top10peakindex from catalog where MW>%d-28 and MW<%d+28" % (self.maxmass, self.maxmass)) self.c = self.cur.fetchall() ms = [] for i in range(len(self.c)): self.basems = np.frombuffer(self.c[i][1], dtype=np.int) cor = self.comnum() if cor > 0.4: temp = (self.c[i][0], cor) ms.append(temp) print ms self.masscor = [] tic = time.time() for i in range(len(ms)): self.cur.execute( "select peakindex, peakintensity from catalog where id=%d" % (ms[i][0])) temp = self.cur.fetchall() masstemp = np.frombuffer(temp[0][0], dtype=np.int) intensitytemp = np.frombuffer(temp[0][1], dtype=np.int) temp2 = (ms[i][0], corrcoef_ms(masstemp, intensitytemp, mz_bin, val_bin)) self.masscor.append(temp2) print time.time() - time0 print time.time() - tic self.masscor.sort(key=lambda d: d[1], reverse=True) for i in range(min(25, len(ms))): self.cur.execute( "select name,Formula,MW from catalog where id=%d" % self.masscor[i][0]) temp = self.cur.fetchall() strsimilarity = '%.2f' % self.masscor[i][1] temp3 = temp[0][1][:-1] temp1 = temp[0][2] temp2 = temp[0][0][:-2] item = QTreeWidgetItem([ str(i + 1), str(strsimilarity), str(temp1), str(temp3), str(temp2) ]) self.library_list.addTopLevelItem(item) if len(ms) > 0: self.showMs(self.masscor[0][0]) zoomer = Qwt.QwtPlotZoomer(Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, Qwt.QwtPicker.DragSelection, Qwt.QwtPicker.AlwaysOn, self.plot1.canvas()) zoomer.setRubberBandPen(QPen(Qt.black)) zoomer.setTrackerPen(QPen(Qt.blue)) self.plot1.zoomer = zoomer self.plot1.zoomer.setZoomBase() def Seach(self): ms = self.ms nist = NISTSearch(NIST_DBPath) nist.top10_screen(self.ms) nist.corr() self.masscor = nist.corrs db = sqlite3.connect(NIST_DBPath) self.cur = db.cursor() for i in range(min(25, len(self.masscor))): self.cur.execute( "select name,Formula,MW from catalog where id=%d" % self.masscor[i][0]) temp = self.cur.fetchall() strsimilarity = '%.2f' % self.masscor[i][1] temp3 = temp[0][1][:-1] temp1 = temp[0][2] temp2 = temp[0][0][:-2] item = QTreeWidgetItem([ str(i + 1), str(strsimilarity), str(temp1), str(temp3), str(temp2) ]) self.library_list.addTopLevelItem(item) if len(ms) > 0: self.showMs(self.masscor[0][0]) zoomer = Qwt.QwtPlotZoomer(Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, Qwt.QwtPicker.DragSelection, Qwt.QwtPicker.AlwaysOn, self.plot1.canvas()) zoomer.setRubberBandPen(QPen(Qt.black)) zoomer.setTrackerPen(QPen(Qt.blue)) self.plot1.zoomer = zoomer self.plot1.zoomer.setZoomBase() def ShowMolFile(self): self.plot3.clear() self.ID = self.row1 Molecular = {} db = sqlite3.connect(MOL_DBPath) cur = db.cursor() cur.execute("select * from catalog where id=%d" % self.ID) c = cur.fetchall() Molecular["MolName"] = c[0][1] Molecular["MolNum"] = c[0][2] Molecular["MolBondNum"] = c[0][3] Molecular["Mol"] = c[0][4].split() Molecular["MolXAxis"] = np.frombuffer(c[0][5], dtype=np.float) Molecular["MolYAxis"] = np.frombuffer(c[0][6], dtype=np.float) Molecular["MolStyle"] = np.frombuffer(c[0][7], dtype=np.int) Molecular["bondX"] = np.frombuffer(c[0][8], dtype=np.int) Molecular["bondY"] = np.frombuffer(c[0][9], dtype=np.int) Molecular["bondNum"] = np.frombuffer(c[0][10], dtype=np.int) self.Molecular = Molecular color = QColor('black') curve = Qwt.QwtPlotCurve() pen = QPen(color) pen.setWidth(1) curve.setPen(pen) curve.setStyle(Qwt.QwtPlotCurve.NoCurve) curve.setSymbol( Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, Qt.black, QPen(Qt.black), QSize(3, 3))) curve.attach(self.plot3) curve.setData(self.Molecular["MolXAxis"], self.Molecular["MolYAxis"]) tempstyl1 = [] tempstyl2 = [] tempstyl3 = [] tempstyl4 = [] for i in range(Molecular["MolBondNum"]): if Molecular["bondNum"][i] == 1 and Molecular["MolStyle"][ Molecular["bondX"][i] - 1] == 0 and Molecular["MolStyle"][Molecular["bondY"][i] - 1] == 0: tempstyl2.append(Molecular["bondX"][i]) tempstyl2.append(Molecular["bondY"][i]) for i in range(Molecular["MolBondNum"]): if Molecular["bondNum"][i] == 2 and Molecular["MolStyle"][ Molecular["bondX"][i] - 1] == 0 and Molecular["MolStyle"][Molecular["bondY"][i] - 1] == 0: if (Molecular["bondX"][i] in tempstyl2) and (Molecular["bondY"][i] in tempstyl2): tempstyl1.append(Molecular["bondX"][i]) tempstyl1.append(Molecular["bondY"][i]) for i in range(len(tempstyl2) / 2): if (tempstyl2[2 * i] in tempstyl1) and (tempstyl2[2 * i + 1] in tempstyl1): tempstyl3.append(tempstyl2[2 * i]) tempstyl3.append(tempstyl2[2 * i + 1]) for i in range(len(tempstyl1) / 2): if (tempstyl1[2 * i] in tempstyl3) and (tempstyl1[2 * i + 1] in tempstyl3): tempstyl4.append(tempstyl1[2 * i]) tempstyl4.append(tempstyl1[2 * i + 1]) tempstyl6 = [] for i in range(len(tempstyl3) / 2): if (tempstyl3[2 * i] in tempstyl4) and (tempstyl3[2 * i + 1] in tempstyl4): tempstyl6.append(tempstyl3[2 * i]) tempstyl6.append(tempstyl3[2 * i + 1]) tempstyl5 = [] # print tempstyl4 while True: if len(tempstyl6) == 0 or len(tempstyl4) == 0: break for i in range(len(tempstyl4) / 2): # print i if not (tempstyl4[2 * i] in tempstyl5): tempindex3 = tempstyl6.index(tempstyl4[2 * i]) tempindex4 = tempstyl6.index(tempstyl4[2 * i + 1]) temp1 = tempstyl4[2 * i] temp2 = tempstyl4[2 * i + 1] if tempindex3 % 2 == 0: temp3 = tempstyl6[tempindex3 + 1] tempindex3other = tempindex3 + 1 else: temp3 = tempstyl6[tempindex3 - 1] tempindex3other = tempindex3 - 1 if tempindex4 % 2 == 0: temp4 = tempstyl6[tempindex4 + 1] tempindex4other = tempindex4 + 1 else: temp4 = tempstyl6[tempindex4 - 1] tempindex4other = tempindex4 - 1 tempindex5 = tempstyl4.index(temp3) tempindex6 = tempstyl4.index(temp4) if tempindex5 % 2 == 0: temp5 = tempstyl4[tempindex5 + 1] else: temp5 = tempstyl4[tempindex5 - 1] if tempindex6 % 2 == 0: temp6 = tempstyl4[tempindex6 + 1] else: temp6 = tempstyl4[tempindex6 - 1] tempindex7 = tempstyl6.index(temp5) if tempindex7 % 2 == 0: temp7 = tempstyl6[tempindex7 + 1] tempindex7other = tempindex7 + 1 else: temp7 = tempstyl6[tempindex7 - 1] tempindex7other = tempindex7 - 1 if temp7 == temp6: if not ((temp1 in tempstyl5) and (temp2 in tempstyl5) and (temp3 in tempstyl5) and (temp4 in tempstyl5) and (temp5 in tempstyl5) and (temp6 in tempstyl5)): tempstyl5.append(temp1) tempstyl5.append(temp2) tempstyl5.append(temp4) tempstyl5.append(temp3) tempstyl5.append(temp6) tempstyl5.append(temp5) temp = [ tempindex3, tempindex3other, tempindex4, tempindex4other, tempindex7, tempindex7other ] temp.sort(reverse=True) del tempstyl6[temp[0]] del tempstyl6[temp[1]] del tempstyl6[temp[2]] del tempstyl6[temp[3]] del tempstyl6[temp[4]] del tempstyl6[temp[5]] for i in np.arange((len(tempstyl4) - 1) / 2, -1, -1): if not (tempstyl4[2 * i] in tempstyl6) or not ( tempstyl4[2 * i + 1] in tempstyl6): del tempstyl4[2 * i + 1] del tempstyl4[2 * i] for i in np.arange((len(tempstyl6) - 1) / 2, -1, -1): if not (tempstyl6[2 * i] in tempstyl4) or not ( tempstyl6[2 * i + 1] in tempstyl4): del tempstyl6[2 * i + 1] del tempstyl6[2 * i] for i in np.arange((len(tempstyl4) - 1) / 2, -1, -1): if not (tempstyl4[2 * i] in tempstyl6) or not ( tempstyl4[2 * i + 1] in tempstyl6): del tempstyl4[2 * i + 1] del tempstyl4[2 * i] for i in np.arange((len(tempstyl6) - 1) / 2, -1, -1): if not (tempstyl6[2 * i] in tempstyl4) or not ( tempstyl6[2 * i + 1] in tempstyl4): del tempstyl6[2 * i + 1] del tempstyl6[2 * i] break # tempstylCom=list(set(tempstyl1) & set(tempstyl2)) # styl=np.setdiff1d(tempstyl1,tempstylCom) for i in range(Molecular["MolBondNum"]): x1 = self.Molecular["MolXAxis"][self.Molecular["bondX"][i] - 1] x2 = self.Molecular["MolXAxis"][self.Molecular["bondY"][i] - 1] y1 = self.Molecular["MolYAxis"][self.Molecular["bondX"][i] - 1] y2 = self.Molecular["MolYAxis"][self.Molecular["bondY"][i] - 1] if (y2 - y1) == 0: Xdiff = 0 Ydiff = np.sqrt(0.003) else: h = (x2 - x1) / (y2 - y1) Xdiff = np.sqrt(0.003 / (h * h + 1)) Ydiff = Xdiff * h if (Molecular["bondNum"][i] == 2) and not (Molecular["bondX"][i] in tempstyl5): tempx1 = [] tempy1 = [] tempx2 = [] tempy2 = [] tempx1.append(x1 + Xdiff) tempx1.append(x2 + Xdiff) tempy1.append(y1 - Ydiff) tempy1.append(y2 - Ydiff) tempx2.append(x1 - Xdiff) tempx2.append(x2 - Xdiff) tempy2.append(y1 + Ydiff) tempy2.append(y2 + Ydiff) curve2 = Qwt.QwtPlotCurve() curve2.setStyle(Qwt.QwtPlotCurve.Lines) curve2.attach(self.plot3) curve2.setData(tempx1, tempy1) curve3 = Qwt.QwtPlotCurve() curve3.setStyle(Qwt.QwtPlotCurve.Lines) curve3.attach(self.plot3) curve3.setData(tempx2, tempy2) elif (Molecular["bondNum"][i] == 3): tempx = [] tempy = [] tempx.append(x1) tempx.append(x2) tempy.append(y1) tempy.append(y2) curve1 = Qwt.QwtPlotCurve() curve1.setStyle(Qwt.QwtPlotCurve.Lines) curve1.attach(self.plot3) curve1.setData(tempx, tempy) tempx1 = [] tempy1 = [] tempx2 = [] tempy2 = [] tempx1.append(x1 + Xdiff) tempx1.append(x2 + Xdiff) tempy1.append(y1 - Ydiff) tempy1.append(y2 - Ydiff) tempx2.append(x1 - Xdiff) tempx2.append(x2 - Xdiff) tempy2.append(y1 + Ydiff) tempy2.append(y2 + Ydiff) curve2 = Qwt.QwtPlotCurve() curve2.setStyle(Qwt.QwtPlotCurve.Lines) curve2.attach(self.plot3) curve2.setData(tempx1, tempy1) curve3 = Qwt.QwtPlotCurve() curve3.setStyle(Qwt.QwtPlotCurve.Lines) curve3.attach(self.plot3) curve3.setData(tempx2, tempy2) else: tempx = [] tempy = [] tempx.append(x1) tempx.append(x2) tempy.append(y1) tempy.append(y2) curve1 = Qwt.QwtPlotCurve() curve1.setStyle(Qwt.QwtPlotCurve.Lines) curve1.attach(self.plot3) curve1.setData(tempx, tempy) t = np.linspace(0, np.pi * 2, 100) diffx1 = np.sin(t) * 0.3 diffy1 = np.cos(t) * 0.3 for i in range(len(tempstyl5) / 6): x0 = 0 y0 = 0 diffx = [] diffy = [] x0 = Molecular["MolXAxis"][tempstyl5[ 6 * i] - 1] + Molecular["MolXAxis"][tempstyl5[6 * i + 1] - 1] x0 = x0 + Molecular["MolXAxis"][tempstyl5[6 * i + 2] - 1] + Molecular["MolXAxis"][ tempstyl5[6 * i + 3] - 1] x0 = x0 + Molecular["MolXAxis"][tempstyl5[6 * i + 4] - 1] + Molecular["MolXAxis"][ tempstyl5[6 * i + 5] - 1] x0 = x0 / 6 y0 = Molecular["MolYAxis"][tempstyl5[ 6 * i] - 1] + Molecular["MolYAxis"][tempstyl5[6 * i + 1] - 1] y0 = y0 + Molecular["MolYAxis"][tempstyl5[6 * i + 2] - 1] + Molecular["MolYAxis"][ tempstyl5[6 * i + 3] - 1] y0 = y0 + Molecular["MolYAxis"][tempstyl5[6 * i + 4] - 1] + Molecular["MolYAxis"][ tempstyl5[6 * i + 5] - 1] y0 = y0 / 6 for i in range(len(diffx1)): diffx.append(diffx1[i] + x0) diffy.append(diffy1[i] + y0) curve4 = Qwt.QwtPlotCurve() curve4.setStyle(Qwt.QwtPlotCurve.Lines) curve4.attach(self.plot3) curve4.setData(diffx, diffy) for i in range(Molecular["MolNum"]): if Molecular["MolStyle"][i] != 0: text = Qwt.QwtText('%s' % Molecular["Mol"][i]) # text=Qwt.QwtText('%s'%str(i+1)) text.setColor(Qt.blue) text.setFont(QFont("Sans", 12)) text.setBackgroundBrush(Qt.white) marker = Qwt.QwtPlotMarker() marker.setLabelAlignment(Qt.AlignCenter | Qt.AlignCenter) marker.setLabel(text) marker.setValue(self.Molecular["MolXAxis"][i], self.Molecular["MolYAxis"][i]) marker.attach(self.plot3) self.plot3.setAxisScale(self.plot3.xBottom, min((min(Molecular["MolXAxis"]) - 0.5), -4), max((max(Molecular["MolXAxis"]) + 0.5), 4)) self.plot3.setAxisScale(self.plot3.yLeft, min((min(Molecular["MolYAxis"]) - 0.5), -4), max((max(Molecular["MolYAxis"]) + 0.5), 4)) self.plot3.replot()
class VersionSelectDialog(QDialog): def __init__(self, parent): # initialize the super class super(VersionSelectDialog, self).__init__(parent) # create the tree self.uiVersionsTREE = QTreeWidget(self) self.uiVersionsTREE.setAlternatingRowColors(True) self.uiVersionsTREE.setRootIsDecorated(False) self.uiVersionsTREE.setSelectionMode(self.uiVersionsTREE.NoSelection) header = self.uiVersionsTREE.header() header.setVisible(False) # create the layout layout = QVBoxLayout() layout.addWidget(self.uiVersionsTREE) layout.setContentsMargins(0, 0, 0, 0) # inherit the highlight palette palette = self.palette() palette.setColor(palette.Highlight, parent.palette().color(palette.Highlight)) self.setPalette(palette) # set dialog information self.setLayout(layout) self.setWindowFlags(Qt.Popup) self.resize(500, 250) # create connections self.uiVersionsTREE.itemClicked.connect(self.acceptItem) def closeEvent(self, event): # update all the items for this for i in range(self.uiVersionsTREE.topLevelItemCount()): item = self.uiVersionsTREE.topLevelItem(i) widget = item.versionWidget() version = widget.version() # match the active state version.setActive(widget.isActive()) super(VersionSelectDialog, self).closeEvent(event) def acceptItem(self, item): # handle version change information widget = item.versionWidget() widget.toggleActive() # accept the dialog self.close() def popup(self, versions): self.uiVersionsTREE.setUpdatesEnabled(False) self.uiVersionsTREE.blockSignals(True) self.uiVersionsTREE.clear() for version in versions: item = VersionItem(self.uiVersionsTREE, version) self.uiVersionsTREE.addTopLevelItem(item) self.uiVersionsTREE.setItemWidget(item, 0, item.versionWidget()) # reset the scrolling self.uiVersionsTREE.verticalScrollBar().setValue(0) self.uiVersionsTREE.setUpdatesEnabled(True) self.uiVersionsTREE.blockSignals(False) return self.exec_()
class UploadEditorDialog(QDialog): def __init__(self, tracks, parent=None): super(UploadEditorDialog, self).__init__(parent) self.setWindowTitle('Upload to Strava') self.setFixedSize(300,200) self.tracks = tracks self._list_widget = QTreeWidget(self) self._list_widget.setColumnCount(2) self._list_widget.setRootIsDecorated(False) self._list_widget.setSortingEnabled(False) self._list_widget.setUniformRowHeights(True) self._list_widget.setSelectionMode(QTreeWidget.NoSelection) self._list_widget.setAlternatingRowColors(True) self._list_widget.header().resizeSection(0, 150) self._list_widget.header().hide() self._fillTable() self._buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self._buttons.accepted.connect(self.accept) self._buttons.rejected.connect(self.reject) self._createLayout() def getValues(self): for t, w in zip(self.tracks, self._widgets): yield t, str(w.currentText()) def eventFilter(self, o, e): if e.type() == QEvent.Wheel and isinstance(o, QComboBox): e.ignore() return True return super(UploadEditorDialog, self).eventFilter(o, e) def _fillTable(self): self._widgets = [] for track in self.tracks: item = QTreeWidgetItem([track['name'], 'ride']) self._list_widget.addTopLevelItem(item) cb = QComboBox() cb.addItems(['ride', 'run']) cb.setFocusPolicy(Qt.ClickFocus) cb.installEventFilter(self) self._list_widget.setItemWidget(item, 1, cb) self._widgets.append(cb) def _createLayout(self): l = QVBoxLayout() l.addWidget(self._list_widget) l.addWidget(self._buttons) self.setLayout(l)
class ThreadsViewer( QWidget ): " Implements the threads viewer for a debugger " def __init__( self, debugger, parent = None ): QWidget.__init__( self, parent ) self.__debugger = debugger self.__createLayout() if Settings().showThreadViewer == False: self.__onShowHide( True ) return def __createLayout( self ): " Creates the widget layout " verticalLayout = QVBoxLayout( self ) verticalLayout.setContentsMargins( 0, 0, 0, 0 ) verticalLayout.setSpacing( 0 ) self.headerFrame = QFrame() self.headerFrame.setFrameStyle( QFrame.StyledPanel ) self.headerFrame.setAutoFillBackground( True ) headerPalette = self.headerFrame.palette() headerBackground = headerPalette.color( QPalette.Background ) headerBackground.setRgb( min( headerBackground.red() + 30, 255 ), min( headerBackground.green() + 30, 255 ), min( headerBackground.blue() + 30, 255 ) ) headerPalette.setColor( QPalette.Background, headerBackground ) self.headerFrame.setPalette( headerPalette ) self.headerFrame.setFixedHeight( 24 ) self.__threadsLabel = QLabel( "Threads" ) expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding ) fixedSpacer = QSpacerItem( 3, 3 ) self.__showHideButton = QToolButton() self.__showHideButton.setAutoRaise( True ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideButton.setFixedSize( 20, 20 ) self.__showHideButton.setToolTip( "Hide threads list" ) self.__showHideButton.setFocusPolicy( Qt.NoFocus ) self.__showHideButton.clicked.connect( self.__onShowHide ) headerLayout = QHBoxLayout() headerLayout.setContentsMargins( 0, 0, 0, 0 ) headerLayout.addSpacerItem( fixedSpacer ) headerLayout.addWidget( self.__threadsLabel ) headerLayout.addSpacerItem( expandingSpacer ) headerLayout.addWidget( self.__showHideButton ) self.headerFrame.setLayout( headerLayout ) self.__threadsList = QTreeWidget() self.__threadsList.setSortingEnabled( False ) # I might not need that because of two reasons: # - the window has no focus # - the window has custom current indicator # self.__threadsList.setAlternatingRowColors( True ) self.__threadsList.setRootIsDecorated( False ) self.__threadsList.setItemsExpandable( False ) self.__threadsList.setUniformRowHeights( True ) self.__threadsList.setSelectionMode( QAbstractItemView.NoSelection ) self.__threadsList.setSelectionBehavior( QAbstractItemView.SelectRows ) self.__threadsList.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__threadsList.setFocusPolicy( Qt.NoFocus ) self.__threadsList.itemClicked.connect( self.__onThreadClicked ) self.__threadsList.setHeaderLabels( [ "", "Name", "State", "TID" ] ) verticalLayout.addWidget( self.headerFrame ) verticalLayout.addWidget( self.__threadsList ) return def __onShowHide( self, startup = False ): " Triggered when show/hide button is clicked " if startup or self.__threadsList.isVisible(): self.__threadsList.setVisible( False ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'more.png' ) ) self.__showHideButton.setToolTip( "Show threads list" ) self.__minH = self.minimumHeight() self.__maxH = self.maximumHeight() self.setMinimumHeight( self.headerFrame.height() ) self.setMaximumHeight( self.headerFrame.height() ) Settings().showThreadViewer = False else: self.__threadsList.setVisible( True ) self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideButton.setToolTip( "Hide threads list" ) self.setMinimumHeight( self.__minH ) self.setMaximumHeight( self.__maxH ) Settings().showThreadViewer = True return def __resizeColumns( self ): " Resize the files list columns " self.__threadsList.header().setStretchLastSection( True ) self.__threadsList.header().resizeSections( QHeaderView.ResizeToContents ) self.__threadsList.header().resizeSection( 0, 22 ) self.__threadsList.header().setResizeMode( 0, QHeaderView.Fixed ) return def clear( self ): " Clears the content " self.__threadsList.clear() self.__threadsLabel.setText( "Threads" ) return def populate( self, currentThreadID, threadList ): " Populates the thread list from the client " self.clear() for thread in threadList: if thread[ 'broken' ]: state = "Waiting at breakpoint" else: state = "Running" item = ThreadItem( thread[ 'id' ], thread[ 'name' ], state ) if thread[ 'id' ] == currentThreadID: item.setCurrent( True ) self.__threadsList.addTopLevelItem( item ) self.__resizeColumns() self.__threadsLabel.setText( "Threads (total: " + str( len( threadList ) ) + ")" ) return def switchControl( self, isInIDE ): " Switches the UI depending where the control flow is " self.__threadsList.setEnabled( isInIDE ) return def __onThreadClicked( self, item, column ): " Triggered when a thread is clicked " if item.isCurrent(): return for index in xrange( self.__threadsList.topLevelItemCount() ): listItem = self.__threadsList.topLevelItem( index ) if listItem.isCurrent(): listItem.setCurrent( False ) break item.setCurrent( True ) self.__debugger.remoteSetThread( item.getTID() ) return
class ElemCompDialog(QtGui.QDialog): def __init__(self,mz, mass,xp,parent=None): QtGui.QDialog.__init__(self, parent) settings = QSettings() size = settings.value("MainWindow/Size",QVariant(QSize(1024,650))).toSize() self.resize(size) self.setWindowTitle('Elenmental Composition') self.xp=xp self.mass=mass self.mz=mz print mz self.initControls() # self.initPlots() def initControls(self): self.plot1 = Qwt.QwtPlot(self) self.plot1.setCanvasBackground(Qt.white) self.plot2 = Qwt.QwtPlot(self) self.plot2.setCanvasBackground(Qt.white) self.list = QTreeWidget() self.list.setColumnCount(11) self.list.setColumnWidth(0,80) self.list.setColumnWidth(1,80) self.list.setColumnWidth(2,60) self.list.setColumnWidth(3,60) self.list.setColumnWidth(4,60) self.list.setColumnWidth(5,150) self.list.setColumnWidth(7,30) self.list.setColumnWidth(8,30) self.list.setColumnWidth(9,30) self.list.setColumnWidth(10,30) self.list.setHeaderLabels(['Mass','Calc.Mass','mDa','PPM','DBE','Formula','Fit Conf %','C','H','N','O']) self.list.setSortingEnabled(True) self.table = QTableWidget(1,11) self.table.setColumnWidth(0,80) self.table.setColumnWidth(1,80) self.table.setColumnWidth(2,60) self.table.setColumnWidth(3,60) self.table.setColumnWidth(4,60) self.table.setColumnWidth(5,150) self.table.setColumnWidth(7,30) self.table.setColumnWidth(8,30) self.table.setColumnWidth(9,30) self.table.setColumnWidth(10,30) self.table.setHorizontalHeaderLabels(['Mass','Calc.Mass','mDa','PPM','DBE','Formula','Fit Conf %','C','H','N','O']) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setSelectionMode(QTableWidget.SingleSelection) self.table.setAlternatingRowColors(True) print self.connect(self.table, SIGNAL("itemActivated(QTableWidgetItem*)"), self.tableClicked) # self.connect(self.library_list, SIGNAL("itemSelectionChanged()"), self.libraryListClicked) up_hbox=QVBoxLayout() up_hbox.addWidget(self.table) down_hbox = QVBoxLayout() down_hbox.addWidget(self.plot1) down_hbox.addWidget(self.plot2) hbox = QVBoxLayout() hbox.addLayout(up_hbox, 3.5) hbox.addLayout(down_hbox, 3.5) self.setLayout(hbox) self.cal_mass() def tableClicked(self,item): self.C=self.table.item(item.row(),7).text() self.H=self.table.item(item.row(),8).text() self.N=self.table.item(item.row(),9).text() self.O=self.table.item(item.row(),10).text() self.cal_isotopic() self.initPlots() def initPlots(self): self.plot1.clear() # self.plot1.setTitle("Observed Isotope Distribution") # self.plot1.setAxisTitle(Qwt.QwtPlot.xBottom, 'Raman shift (cm-1)') # self.plot1.setAxisTitle(Qwt.QwtPlot.yLeft, 'Intensity') # grid = Qwt.QwtPlotGrid() pen = QPen(Qt.DotLine) pen.setColor(Qt.black) pen.setWidth(0) # grid.setPen(pen) # grid.attach(self.plot1) self.mass1=self.mass/self.massy*100 self.plot1.setAxisScale(self.plot1.xBottom,self.x_min,self.x_max) self.plot1.setAxisScale(self.plot1.yLeft,0,1.1*100) color = QColor('black') curve = Qwt.QwtPlotCurve("test1") pen = QPen(color) pen.setWidth(1) curve.setPen(pen) curve.setData(self.mass_x,self.mass_y) curve.setStyle(Qwt.QwtPlotCurve.Sticks) curve.attach(self.plot1) self.plot1.replot() self.plot2.clear() # self.plot2.setTitle("Theoretical Isotope Distribution") # self.plot2.setAxisTitle(Qwt.QwtPlot.xBottom, 'Raman shift (cm-1)') # self.plot2.setAxisTitle(Qwt.QwtPlot.yLeft, 'Intensity') # grid = Qwt.QwtPlotGrid() pen = QPen(Qt.DotLine) pen.setColor(Qt.blue) self.plot2.setAxisScale(self.plot1.xBottom,self.x_min,self.x_max) self.plot2.setAxisScale(self.plot1.yLeft,0,1.1*100) color = QColor('blue') curve = Qwt.QwtPlotCurve("test1") pen = QPen(color) pen.setWidth(1) curve.setPen(pen) # self.axis= np.arange(len(self.mass)) curve.setData(self.x,self.y) curve.setStyle(Qwt.QwtPlotCurve.Sticks) curve.attach(self.plot2) pen.setWidth(0) # grid.setPen(pen) # grid.attach(self.plot2) self.plot2.replot() def cal_mass(self): # charge=0.0 tol = 10.0 # electron=0.000549 measured_mass=np.round(self.xp) limit_lo = measured_mass - (tol/1000.0) limit_hi = measured_mass + (tol/1000.0) mass=[] mass.append((12.000000000,2.0,"C")) #mass.append((78.9183376,-1.0,"Br")) #mass.append((34.96885271,-1.0,"Cl")) #mass.append((31.97207069,0.0,"S")) #mass.append((30.97376151,1.0,"P")) #mass.append((27.9769265327,2.0,"Si")) #mass.append((22.98976967,-1.0,"Na")) #mass.append((18.99840320,-1.0,"F")) mass.append((15.9949146221,0.0,"O")) mass.append((14.0030740052,1.0,"N")) mass.append((1.0078250321,-1.0,"H")) print range(1,10) print mass[0][0] print mass[1][0] print mass[2][0] calc_mass=[] for i in range(1,int(floor(measured_mass/mass[0][0]))+1): for j in range(0,int(floor((measured_mass-mass[0][0]*i)/mass[1][0]))+1): for k in range(0,int(floor((measured_mass-mass[0][0]*i-mass[1][0]*j)/mass[2][0]))+1): # rr=(measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0] # rrr=round((measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0]) # rrrr=int(round((measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0])) # print "rr:%s"%rr+" rrr:%s"%rrr+" rrrr:%s"%rrrr r=int(round((measured_mass-mass[0][0]*i-mass[1][0]*j-mass[2][0]*k)/mass[3][0])) calmass=mass[0][0]*i+mass[1][0]*j+mass[2][0]*k+mass[3][0]*r if (mass[0][1]*i+mass[2][1]*k+mass[3][1]*r)>=-1 and calmass>limit_lo and calmass<limit_hi: calc_mass.append((calmass,i,j,k,r)) print len(calc_mass) for ii in range(0,len(calc_mass)): mda=(measured_mass-calc_mass[ii][0])*1000 ppm=(measured_mass-calc_mass[ii][0])/measured_mass*1000000 DBE=(calc_mass[ii][1]*2+calc_mass[ii][3]-calc_mass[ii][4]+2)/2.0 self.calmass="%.4f"%calc_mass[ii][0] self.mda="%.1f"%mda self.ppm="%.1f"%ppm self.DBE="%.1f"%DBE self.C="%s"%calc_mass[ii][1] self.H="%s"%calc_mass[ii][4] self.N="%s"%calc_mass[ii][3] self.O="%s"%calc_mass[ii][2] self.Formula="C%2s"%self.C+" H%2s"%self.H+" N%2s"%self.N+" O%2s"%self.O mass=str(self.xp) # if not(ii==0): # mass="" self.cal_isotopic() self.initPlots() self.conf="%.1f"%self.mass_diff self.table.insertRow(ii) self.table.setRowHeight(ii,20) self.table.setItem(ii, 0,QTableWidgetItem(mass)) self.table.setItem(ii, 1,QTableWidgetItem(self.calmass)) self.table.setItem(ii, 2,QTableWidgetItem(self.mda)) self.table.setItem(ii, 3,QTableWidgetItem(self.ppm)) self.table.setItem(ii, 4,QTableWidgetItem(self.DBE)) self.table.setItem(ii, 5,QTableWidgetItem(self.Formula)) self.table.setItem(ii, 6,QTableWidgetItem(self.conf)) self.table.setItem(ii, 7,QTableWidgetItem(self.C)) self.table.setItem(ii, 8,QTableWidgetItem(self.H)) self.table.setItem(ii, 9,QTableWidgetItem(self.N)) self.table.setItem(ii, 10,QTableWidgetItem(self.O)) item=QTreeWidgetItem([mass,str(self.calmass),str(self.mda),str(self.ppm),str(self.DBE),self.Formula,str(self.conf),str(self.C),str(self.H),str(self.N),str(self.O)]) self.list.addTopLevelItem(item) self.table.removeRow(len(calc_mass)) self.table.setSortingEnabled(True) # self.table.sortByColumn(1,Qt.DescendingOrder) def next2pow(self): return 2**int(np.ceil(np.log(float(self.xx))/np.log(2.0))) def cal_isotopic(self): MAX_ELEMENTS=5+1 # add 1 due to mass correction 'element' MAX_ISOTOPES=4 # maxiumum # of isotopes for one element CUTOFF=1e-4 # relative intensity cutoff for plotting WINDOW_SIZE = 500 #WINDOW_SIZE=input('Window size (in Da) ---> '); #RESOLUTION=input('Resolution (in Da) ----> '); % mass unit used in vectors RESOLUTION = 1 if RESOLUTION < 0.00001:# % minimal mass step allowed RESOLUTION = 0.00001 elif RESOLUTION > 0.5: # maximal mass step allowed RESOLUTION = 0.5 R=0.00001/RESOLUTION# % R is used to scale nuclide masses (see below) WINDOW_SIZE=WINDOW_SIZE/RESOLUTION; self.xx=WINDOW_SIZE # convert window size to new mass units WINDOW_SIZE=self.next2pow(); # fast radix-2 fast-Fourier transform algorithm if WINDOW_SIZE < np.round(496708*R)+1: WINDOW_SIZE = self.next2pow(np.round(496708*R)+1) # just to make sure window is big enough #H378 C254 N65 O75 S6 M=np.array([int(self.H),int(self.C),int(self.N),int(self.O),0,0]) #% empiric formula, e.g. bovine insulin # isotopic abundances stored in matrix A (one row for each element) A=np.zeros((MAX_ELEMENTS,MAX_ISOTOPES,2)); A[0][0,:] = [100783,0.9998443]# % 1H A[0][1,:] = [201410,0.0001557]# % 2H A[1][0,:] = [100000,0.98889]# % 12C A[1][1,:] = [200336,0.01111]# % 13C A[2][0,:] = [100307,0.99634]# % 14N A[2][1,:] = [200011,0.00366]# % 15N A[3][0,:] = [99492,0.997628]# % 16O A[3][1,:] = [199913,0.000372]# % 17O A[3][2,:] = [299916,0.002000]# % 18O A[4][0,:] = [97207,0.95018]# % 32S A[4][1,:] = [197146,0.00750]# % 33S A[4][2,:] = [296787,0.04215]# % 34S A[4][3,:] = [496708,0.00017]# % 36S A[5][0,:] = [100000,1.00000]# % for shifting mass so that Mmi is # % near left limit of window Mmi=np.array([np.round(100783*R), np.round(100000*R),\ np.round(100307*R),np.round(99492*R), np.round(97207*R), 0])*M# % (Virtual) monoisotopic mass in new units Mmi = Mmi.sum() #% mass shift so Mmi is in left limit of window: FOLDED=np.floor(Mmi/(WINDOW_SIZE-1))+1# % folded FOLDED times (always one folding due to shift below) #% shift distribution to 1 Da from lower window limit: M[MAX_ELEMENTS-1]=np.ceil(((WINDOW_SIZE-1)-np.mod(Mmi,WINDOW_SIZE-1)+np.round(100000*R))*RESOLUTION) MASS_REMOVED=np.array([0,11,13,15,31,-1])*M#% correction for 'virtual' elements and mass shift begin=WINDOW_SIZE*RESOLUTION+MASS_REMOVED.sum() end=2*(WINDOW_SIZE-1)*RESOLUTION+MASS_REMOVED.sum() ptA=np.ones(WINDOW_SIZE); t_fft=0 t_mult=0 for i in xrange(MAX_ELEMENTS): tA=np.zeros(WINDOW_SIZE) for j in xrange(MAX_ISOTOPES): if A[i][j,0] != 0: #removed +1 after R)+1 --we're using python tA[np.round(A[i][j,0]*R)]=A[i][j,1]#; % put isotopic distribution in tA t0 = time.clock() tA=F.fft(tA) # FFT along elements isotopic distribution O(nlogn) t_fft = time.clock()-t0 t0 = time.clock() tA=tA**M[i]# % O(n) ################# ptA = ptA*tA# % O(n)#this is where it is messing UP ################# t1 = time.clock() t_mult=t1-t0 t0=time.clock() ptA=F.ifft(ptA).real#; % O(nlogn) t0=time.clock() MA=np.linspace(begin,end,WINDOW_SIZE-1) ind=np.where(ptA>CUTOFF)[0] self.x = MA[ind] self.y = ptA[ind] self.x_min=int(np.min(self.x)-(np.max(self.x)-np.min(self.x))) self.x_max=int(np.min(self.x)+(np.max(self.x)-np.min(self.x))) self.mass_y=np.ones(len(self.x)) mass_diff=np.ones(len(self.x)) mzInd= np.logical_and((self.mz>=self.x_min),(self.mz<=self.x_max)) self.mass_y=self.mass[mzInd] self.mass_x=self.mz[mzInd] # for i in range(len(self.x)): # self.mass_y[i]=self.mass[int(self.x[i])] self.massy=np.max(self.mass_y) print self.massy self.mass_y=self.mass_y/max(self.mass_y)*100 self.y=self.y/max(self.y)*100 # k=(self.mass_y*self.y).sum()/(self.mass_y*self.mass_y).sum() # self.fit=((k*self.mass_y-self.y)*(k*self.mass_y-self.y)).sum()/(self.y*self.y).sum() for i in range(len(self.y)): mass_diff[i]=np.abs(self.mass_y[i]-self.y[i])/(self.mass_y[i]+self.y[i]) self.mass_diff=(1-mass_diff.sum()/len(mass_diff))*100
class EditorConfiguration(QWidget): """EditorConfiguration widget class""" def __init__(self, parent): super(EditorConfiguration, self).__init__() self._preferences, vbox = parent, QVBoxLayout(self) # groups group1 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_INDENT) group2 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_MARGIN) group3 = QGroupBox(translations.TR_LINT_DIRTY_TEXT) group4 = QGroupBox(translations.TR_PEP8_DIRTY_TEXT) group5 = QGroupBox(translations.TR_HIGHLIGHTER_EXTRAS) group6 = QGroupBox(translations.TR_TYPING_ASSISTANCE) group7 = QGroupBox(translations.TR_DISPLAY) # groups container container_widget_with_all_preferences = QWidget() formFeatures = QGridLayout(container_widget_with_all_preferences) # Indentation hboxg1 = QHBoxLayout(group1) hboxg1.setContentsMargins(5, 15, 5, 5) self._spin, self._checkUseTabs = QSpinBox(), QComboBox() self._spin.setRange(1, 10) self._spin.setValue(settings.INDENT) hboxg1.addWidget(self._spin) self._checkUseTabs.addItems([ translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES.capitalize(), translations.TR_PREFERENCES_EDITOR_CONFIG_TABS.capitalize()]) self._checkUseTabs.setCurrentIndex(int(settings.USE_TABS)) hboxg1.addWidget(self._checkUseTabs) formFeatures.addWidget(group1, 0, 0) # Margin Line hboxg2 = QHBoxLayout(group2) hboxg2.setContentsMargins(5, 15, 5, 5) self._checkShowMargin = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MARGIN_LINE) self._checkShowMargin.setChecked(settings.SHOW_MARGIN_LINE) hboxg2.addWidget(self._checkShowMargin) self._spinMargin = QSpinBox() self._spinMargin.setRange(50, 100) self._spinMargin.setSingleStep(2) self._spinMargin.setValue(settings.MARGIN_LINE) hboxg2.addWidget(self._spinMargin) hboxg2.addWidget(QLabel(translations.TR_CHARACTERS)) formFeatures.addWidget(group2, 0, 1) # Display Errors vboxDisplay = QVBoxLayout(group7) vboxDisplay.setContentsMargins(5, 15, 5, 5) self._checkHighlightLine = QComboBox() self._checkHighlightLine.addItems([ translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_BACKGROUND, translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_UNDERLINE]) self._checkHighlightLine.setCurrentIndex( int(settings.UNDERLINE_NOT_BACKGROUND)) hboxDisplay1 = QHBoxLayout() hboxDisplay1.addWidget(QLabel(translations.TR_DISPLAY_ERRORS)) hboxDisplay1.addWidget(self._checkHighlightLine) hboxDisplay2 = QHBoxLayout() self._checkDisplayLineNumbers = QCheckBox( translations.TR_DISPLAY_LINE_NUMBERS) self._checkDisplayLineNumbers.setChecked(settings.SHOW_LINE_NUMBERS) hboxDisplay2.addWidget(self._checkDisplayLineNumbers) vboxDisplay.addLayout(hboxDisplay1) vboxDisplay.addLayout(hboxDisplay2) formFeatures.addWidget(group7, 1, 0, 1, 0) # Find Lint Errors (highlighter) vboxg3 = QVBoxLayout(group3) self._checkErrors = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_FIND_ERRORS) self._checkErrors.setChecked(settings.FIND_ERRORS) self.connect(self._checkErrors, SIGNAL("stateChanged(int)"), self._disable_show_errors) self._showErrorsOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_ERRORS) self._showErrorsOnLine.setChecked(settings.ERRORS_HIGHLIGHT_LINE) self.connect(self._showErrorsOnLine, SIGNAL("stateChanged(int)"), self._enable_errors_inline) vboxg3.addWidget(self._checkErrors) vboxg3.addWidget(self._showErrorsOnLine) vboxg3.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) formFeatures.addWidget(group3, 2, 0) # Find PEP8 Errors (highlighter) vboxg4 = QHBoxLayout(group4) vboxg4.setContentsMargins(5, 15, 5, 5) vvbox = QVBoxLayout() self._checkStyle = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_PEP8) self._checkStyle.setChecked(settings.CHECK_STYLE) self.connect(self._checkStyle, SIGNAL("stateChanged(int)"), self._disable_check_style) vvbox.addWidget(self._checkStyle) self._checkStyleOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_PEP8) self._checkStyleOnLine.setChecked(settings.CHECK_HIGHLIGHT_LINE) self.connect(self._checkStyleOnLine, SIGNAL("stateChanged(int)"), self._enable_check_inline) vvbox.addWidget(self._checkStyleOnLine) vvbox.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) vboxg4.addLayout(vvbox) # Container for tree widget and buttons widget = QWidget() hhbox = QHBoxLayout(widget) hhbox.setContentsMargins(0, 0, 0, 0) # Tree Widget with custom item delegate # always adds uppercase text self._listIgnoreViolations = QTreeWidget() self._listIgnoreViolations.setObjectName("ignore_pep8") self._listIgnoreViolations.setItemDelegate(ui_tools.CustomDelegate()) self._listIgnoreViolations.setMaximumHeight(80) self._listIgnoreViolations.setHeaderLabel( translations.TR_PREFERENCES_EDITOR_CONFIG_IGNORE_PEP8) for ic in settings.IGNORE_PEP8_LIST: self._listIgnoreViolations.addTopLevelItem(QTreeWidgetItem([ic])) hhbox.addWidget(self._listIgnoreViolations) box = QVBoxLayout() box.setContentsMargins(0, 0, 0, 0) btn_add = QPushButton(QIcon(":img/add_small"), '') btn_add.setMaximumSize(26, 24) btn_add.clicked.connect(self._add_code_pep8) box.addWidget(btn_add) btn_remove = QPushButton(QIcon(":img/delete_small"), '') btn_remove.setMaximumSize(26, 24) btn_remove.clicked.connect(self._remove_code_pep8) box.addWidget(btn_remove) box.addItem(QSpacerItem(0, 0, QSizePolicy.Fixed, QSizePolicy.Expanding)) hhbox.addLayout(box) vboxg4.addWidget(widget) formFeatures.addWidget(group4) # Show Python3 Migration, DocStrings and Spaces (highlighter) vboxg5 = QVBoxLayout(group5) vboxg5.setContentsMargins(5, 15, 5, 5) self._showMigrationTips = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MIGRATION) self._showMigrationTips.setChecked(settings.SHOW_MIGRATION_TIPS) vboxg5.addWidget(self._showMigrationTips) self._checkForDocstrings = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_CHECK_FOR_DOCSTRINGS) self._checkForDocstrings.setChecked(settings.CHECK_FOR_DOCSTRINGS) vboxg5.addWidget(self._checkForDocstrings) self._checkShowSpaces = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TABS_AND_SPACES) self._checkShowSpaces.setChecked(settings.SHOW_TABS_AND_SPACES) vboxg5.addWidget(self._checkShowSpaces) self._checkIndentationGuide = QCheckBox( translations.TR_SHOW_INDENTATION_GUIDE) self._checkIndentationGuide.setChecked(settings.SHOW_INDENTATION_GUIDE) vboxg5.addWidget(self._checkIndentationGuide) formFeatures.addWidget(group5, 3, 0) # End of line, Stop Scrolling At Last Line, Trailing space, Word wrap vboxg6 = QVBoxLayout(group6) vboxg6.setContentsMargins(5, 15, 5, 5) self._checkEndOfLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_END_OF_LINE) self._checkEndOfLine.setChecked(settings.USE_PLATFORM_END_OF_LINE) vboxg6.addWidget(self._checkEndOfLine) self._checkEndAtLastLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_END_AT_LAST_LINE) self._checkEndAtLastLine.setChecked(settings.END_AT_LAST_LINE) vboxg6.addWidget(self._checkEndAtLastLine) self._checkTrailing = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_REMOVE_TRAILING) self._checkTrailing.setChecked(settings.REMOVE_TRAILING_SPACES) vboxg6.addWidget(self._checkTrailing) self._allowWordWrap = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_WORD_WRAP) self._allowWordWrap.setChecked(settings.ALLOW_WORD_WRAP) vboxg6.addWidget(self._allowWordWrap) formFeatures.addWidget(group6, 3, 1) # pack all the groups vbox.addWidget(container_widget_with_all_preferences) vbox.addItem(QSpacerItem(0, 10, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.connect(self._preferences, SIGNAL("savePreferences()"), self.save) def _add_code_pep8(self): item = QTreeWidgetItem() item.setFlags(item.flags() | Qt.ItemIsEditable) self._listIgnoreViolations.addTopLevelItem(item) self._listIgnoreViolations.setCurrentItem(item) self._listIgnoreViolations.editItem(item, 0) def _remove_code_pep8(self): index = self._listIgnoreViolations.indexOfTopLevelItem( self._listIgnoreViolations.currentItem()) self._listIgnoreViolations.takeTopLevelItem(index) def _enable_check_inline(self, val): """Method that takes a value to enable the inline style checking""" if val == Qt.Checked: self._checkStyle.setChecked(True) def _enable_errors_inline(self, val): """Method that takes a value to enable the inline errors checking""" if val == Qt.Checked: self._checkErrors.setChecked(True) def _disable_check_style(self, val): """Method that takes a value to disable the inline style checking""" if val == Qt.Unchecked: self._checkStyleOnLine.setChecked(False) def _disable_show_errors(self, val): """Method that takes a value to disable the inline errors checking""" if val == Qt.Unchecked: self._showErrorsOnLine.setChecked(False) def save(self): """Method to save settings""" qsettings = IDE.ninja_settings() settings.USE_TABS = bool(self._checkUseTabs.currentIndex()) qsettings.setValue('preferences/editor/useTabs', settings.USE_TABS) margin_line = self._spinMargin.value() settings.MARGIN_LINE = margin_line settings.pycodestylemod_update_margin_line_length(margin_line) qsettings.setValue('preferences/editor/marginLine', margin_line) settings.SHOW_MARGIN_LINE = self._checkShowMargin.isChecked() qsettings.setValue('preferences/editor/showMarginLine', settings.SHOW_MARGIN_LINE) settings.INDENT = self._spin.value() qsettings.setValue('preferences/editor/indent', settings.INDENT) endOfLine = self._checkEndOfLine.isChecked() settings.USE_PLATFORM_END_OF_LINE = endOfLine qsettings.setValue('preferences/editor/platformEndOfLine', endOfLine) settings.UNDERLINE_NOT_BACKGROUND = \ bool(self._checkHighlightLine.currentIndex()) qsettings.setValue('preferences/editor/errorsUnderlineBackground', settings.UNDERLINE_NOT_BACKGROUND) settings.FIND_ERRORS = self._checkErrors.isChecked() qsettings.setValue('preferences/editor/errors', settings.FIND_ERRORS) settings.ERRORS_HIGHLIGHT_LINE = self._showErrorsOnLine.isChecked() qsettings.setValue('preferences/editor/errorsInLine', settings.ERRORS_HIGHLIGHT_LINE) settings.CHECK_STYLE = self._checkStyle.isChecked() qsettings.setValue('preferences/editor/checkStyle', settings.CHECK_STYLE) settings.SHOW_MIGRATION_TIPS = self._showMigrationTips.isChecked() qsettings.setValue('preferences/editor/showMigrationTips', settings.SHOW_MIGRATION_TIPS) settings.CHECK_HIGHLIGHT_LINE = self._checkStyleOnLine.isChecked() qsettings.setValue('preferences/editor/checkStyleInline', settings.CHECK_HIGHLIGHT_LINE) settings.END_AT_LAST_LINE = self._checkEndAtLastLine.isChecked() qsettings.setValue('preferences/editor/endAtLastLine', settings.END_AT_LAST_LINE) settings.REMOVE_TRAILING_SPACES = self._checkTrailing.isChecked() qsettings.setValue('preferences/editor/removeTrailingSpaces', settings.REMOVE_TRAILING_SPACES) settings.ALLOW_WORD_WRAP = self._allowWordWrap.isChecked() qsettings.setValue('preferences/editor/allowWordWrap', settings.ALLOW_WORD_WRAP) settings.SHOW_TABS_AND_SPACES = self._checkShowSpaces.isChecked() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) settings.SHOW_INDENTATION_GUIDE = ( self._checkIndentationGuide.isChecked()) qsettings.setValue('preferences/editor/showIndentationGuide', settings.SHOW_INDENTATION_GUIDE) settings.CHECK_FOR_DOCSTRINGS = self._checkForDocstrings.isChecked() qsettings.setValue('preferences/editor/checkForDocstrings', settings.CHECK_FOR_DOCSTRINGS) settings.SHOW_LINE_NUMBERS = self._checkDisplayLineNumbers.isChecked() qsettings.setValue('preferences/editor/showLineNumbers', settings.SHOW_LINE_NUMBERS) current_ignores = set(settings.IGNORE_PEP8_LIST) new_ignore_codes = [] # Get pep8 from tree widget for index in range(self._listIgnoreViolations.topLevelItemCount()): ignore_code = self._listIgnoreViolations.topLevelItem( index).text(0) if ignore_code: new_ignore_codes.append(ignore_code.strip()) # pep8 list that will be removed to_remove = [x for x in current_ignores if x not in new_ignore_codes] # Update list settings.IGNORE_PEP8_LIST = new_ignore_codes qsettings.setValue('preferences/editor/defaultIgnorePep8', settings.IGNORE_PEP8_LIST) # Add for ignore_code in settings.IGNORE_PEP8_LIST: settings.pycodestylemod_add_ignore(ignore_code) # Remove for ignore_code in to_remove: settings.pycodestylemod_remove_ignore(ignore_code) if settings.USE_TABS: settings.pycodestylemod_add_ignore("W191") else: settings.pycodestylemod_remove_ignore("W191")
class Preferences(QDialog): configuration = {} weight = 0 def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(800, 600)) self.setMaximumSize(QSize(0, 0)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) self.connect(self.tree, SIGNAL("itemSelectionChanged()"), self._change_current) self.connect(self._btnCancel, SIGNAL("clicked()"), self.close) self.connect(self._btnSave, SIGNAL("clicked()"), self._save_preferences) self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0)) def _save_preferences(self): self.emit(SIGNAL("savePreferences()")) self.close() def load_ui(self): sections = sorted( list(Preferences.configuration.keys()), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) index = self.stacked.addWidget(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) #Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted(list(subcontent.keys()), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) index = self.stacked.addWidget(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) self.tree.expandAll() def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if not subsection: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config
class PluginsDialog(QDialog): " Codimension plugins dialog " def __init__(self, pluginManager, parent=None): QDialog.__init__(self, parent) self.setWindowTitle("Plugin Manager") self.__pluginManager = pluginManager self.__configFuncs = {} # int -> callable self.__createLayout() self.__populate() self.__pluginsView.setFocus() self.__inItemChange = False return def __createLayout(self): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors(True) self.__pluginsView.setRootIsDecorated(False) self.__pluginsView.setItemsExpandable(False) self.__pluginsView.setSortingEnabled(True) self.__pluginsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.__pluginsView.setUniformRowHeights(True) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( ["", "", "", "Name", "Version", ""]) self.__pluginsView.setHeaderItem(self.__pluginsHeader) self.__pluginsView.header().setSortIndicator(NAME_COL, Qt.AscendingOrder) self.connect(self.__pluginsView, SIGNAL("itemSelectionChanged()"), self.__pluginSelectionChanged) self.connect(self.__pluginsView, SIGNAL("itemChanged(QTreeWidgetItem*,int)"), self.__onItemChanged) layout.addWidget(self.__pluginsView) # Detailed information detailsLabel = QLabel("Detailed information") layout.addWidget(detailsLabel) self.__details = QTreeWidget() self.__details.setAlternatingRowColors(False) self.__details.setRootIsDecorated(False) self.__details.setItemsExpandable(False) self.__details.setSortingEnabled(False) self.__details.setItemDelegate(NoOutlineHeightDelegate(4)) self.__details.setUniformRowHeights(True) detailsHeader = QTreeWidgetItem(["", ""]) self.__details.setHeaderItem(detailsHeader) self.__details.setHeaderHidden(True) metrics = QFontMetrics(self.__details.font()) rect = metrics.boundingRect("X") self.__details.setFixedHeight(rect.height() * 6 + 5) layout.addWidget(self.__details) # Errors/warnings errorsLabel = QLabel("Errors / warnings") layout.addWidget(errorsLabel) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly(True) self.__errorsText.setAcceptRichText(False) metrics = QFontMetrics(self.__errorsText.font()) rect = metrics.boundingRect("X") self.__errorsText.setFixedHeight(rect.height() * 4 + 5) layout.addWidget(self.__errorsText) # Buttons box buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.__OKButton = buttonBox.button(QDialogButtonBox.Ok) self.__OKButton.setDefault(True) self.connect(buttonBox, SIGNAL("accepted()"), self.close) self.connect(buttonBox, SIGNAL("rejected()"), self.close) layout.addWidget(buttonBox) self.setLayout(layout) return def __createConfigButton(self): " Creates a configure button for a plugin " button = SettingsButton() self.connect(button, SIGNAL('CustomClick'), self.onPluginSettings) return button def __populate(self): " Populates the list with the plugins " index = 0 for category in self.__pluginManager.activePlugins: for cdmPlugin in self.__pluginManager.activePlugins[category]: newItem = PluginItem(self.__pluginManager, cdmPlugin, True, category) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring") settingsButton.setEnabled(False) else: settingsButton.setToolTip("Click to configure") settingsButton.setEnabled(True) self.__configFuncs[index] = configFunction settingsButton.index = index index += 1 except Exception: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received.") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) for category in self.__pluginManager.inactivePlugins: for cdmPlugin in self.__pluginManager.inactivePlugins[category]: newItem = PluginItem(self.__pluginManager, cdmPlugin, False, category) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring") settingsButton.setEnabled(False) else: settingsButton.setToolTip( "Enable plugin and then click to configure") settingsButton.setEnabled(False) self.__configFuncs[index] = configFunction settingsButton.index = index index += 1 except: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received.") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) for cdmPlugin in self.__pluginManager.unknownPlugins: newItem = PluginItem(self.__pluginManager, cdmPlugin, False, None) self.__pluginsView.addTopLevelItem(newItem) settingsButton = self.__createConfigButton() settingsButton.setToolTip("Unknown plugins are not configurable") settingsButton.setEnabled(False) self.__pluginsView.setItemWidget(newItem, SETTINGS_COL, settingsButton) self.__sortPlugins() self.__resizePlugins() return def __sortPlugins(self): " Sorts the plugins table " self.__pluginsView.sortItems( self.__pluginsView.sortColumn(), self.__pluginsView.header().sortIndicatorOrder()) return def __resizePlugins(self): " Resizes the plugins table " self.__pluginsView.header().setStretchLastSection(False) self.__pluginsView.header().resizeSections( QHeaderView.ResizeToContents) self.__pluginsView.header().resizeSection(STATE_COL, 28) self.__pluginsView.header().setResizeMode(STATE_COL, QHeaderView.Fixed) self.__pluginsView.header().resizeSection(CONFLICT_COL, 28) self.__pluginsView.header().setResizeMode(CONFLICT_COL, QHeaderView.Fixed) self.__pluginsView.header().resizeSection(TYPE_COL, 28) self.__pluginsView.header().setResizeMode(TYPE_COL, QHeaderView.Fixed) self.__pluginsView.header().setResizeMode(VERSION_COL, QHeaderView.Stretch) self.__pluginsView.header().resizeSection(SETTINGS_COL, 24) self.__pluginsView.header().setResizeMode(SETTINGS_COL, QHeaderView.Fixed) return def __pluginSelectionChanged(self): " Triggered when an item is selected " selected = list(self.__pluginsView.selectedItems()) if selected: self.__updateDetails(selected[0]) else: self.__updateDetails(None) return def __updateDetails(self, item): " Updates the content of the details and the error boxes " self.__details.clear() self.__errorsText.setText("") if item is None: return self.__details.addTopLevelItem( QTreeWidgetItem(["Author", item.plugin.getAuthor()])) self.__details.addTopLevelItem( QTreeWidgetItem(["Path", os.path.normpath(item.plugin.getPath())])) self.__details.addTopLevelItem( QTreeWidgetItem(["Description", item.plugin.getDescription()])) self.__details.addTopLevelItem( QTreeWidgetItem(["Web site", item.plugin.getWebsite()])) copyright = item.plugin.getCopyright() if copyright is not None: if copyright.lower() != "unknown": self.__details.addTopLevelItem( QTreeWidgetItem(["Copyright", copyright])) for name in item.plugin.getDetails(): value = item.plugin.getDetails()[name] self.__details.addTopLevelItem(QTreeWidgetItem([name, value])) self.__errorsText.setText(item.plugin.conflictMessage) return def __onItemChanged(self, item, column): " Triggered when an item is changed " if self.__inItemChange: return if item.active: self.__inItemChange = True item.plugin.disable() item.active = False settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL) settingsButton.setEnabled(False) if settingsButton.index != -1: settingsButton.setToolTip( "Enable plugin and then click to configure") if item.category in self.__pluginManager.inactivePlugins: self.__pluginManager.inactivePlugins[item.category].append( item.plugin) else: self.__pluginManager.inactivePlugins[item.category] = [ item.plugin ] self.__pluginManager.activePlugins[item.category].remove( item.plugin) self.__pluginManager.saveDisabledPlugins() self.__inItemChange = False self.__pluginManager.sendPluginDeactivated(item.plugin) return self.__inItemChange = True message = self.__pluginManager.checkConflict(item.plugin) if message is not None: item.setCheckState(STATE_COL, Qt.Unchecked) self.__errorsText.setText(message) self.__inItemChange = False return try: item.plugin.enable() item.active = True if item.category in self.__pluginManager.activePlugins: self.__pluginManager.activePlugins[item.category].append( item.plugin) else: self.__pluginManager.activePlugins[item.category] = [ item.plugin ] self.__pluginManager.inactivePlugins[item.category].remove( item.plugin) self.__pluginManager.saveDisabledPlugins() self.__errorsText.setText("") item.setIcon(CONFLICT_COL, PixmapCache().getIcon('empty.png')) item.setToolTip(CONFLICT_COL, "") settingsButton = self.__pluginsView.itemWidget(item, SETTINGS_COL) if settingsButton.index != -1: settingsButton.setToolTip("Click to configure") settingsButton.setEnabled(True) self.__pluginManager.sendPluginActivated(item.plugin) except: item.setCheckState(STATE_COL, Qt.Unchecked) self.__errorsText.setText( "Error activating the plugin - exception is generated") self.__inItemChange = False return def onPluginSettings(self, index): " Triggered when a configuring function is called " if index not in self.__configFuncs: return try: self.__configFuncs[index]() except Exception, exc: logging.error("Error calling the plugin configuration function. " "Message: " + str(exc)) return
class ThreadsViewer(QWidget): " Implements the threads viewer for a debugger " def __init__(self, debugger, parent=None): QWidget.__init__(self, parent) self.__debugger = debugger self.__createLayout() if Settings().showThreadViewer == False: self.__onShowHide(True) return def __createLayout(self): " Creates the widget layout " verticalLayout = QVBoxLayout(self) verticalLayout.setContentsMargins(0, 0, 0, 0) verticalLayout.setSpacing(0) self.headerFrame = QFrame() self.headerFrame.setFrameStyle(QFrame.StyledPanel) self.headerFrame.setAutoFillBackground(True) headerPalette = self.headerFrame.palette() headerBackground = headerPalette.color(QPalette.Background) headerBackground.setRgb(min(headerBackground.red() + 30, 255), min(headerBackground.green() + 30, 255), min(headerBackground.blue() + 30, 255)) headerPalette.setColor(QPalette.Background, headerBackground) self.headerFrame.setPalette(headerPalette) self.headerFrame.setFixedHeight(24) self.__threadsLabel = QLabel("Threads") expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding) fixedSpacer = QSpacerItem(3, 3) self.__showHideButton = QToolButton() self.__showHideButton.setAutoRaise(True) self.__showHideButton.setIcon(PixmapCache().getIcon('less.png')) self.__showHideButton.setFixedSize(20, 20) self.__showHideButton.setToolTip("Hide threads list") self.__showHideButton.setFocusPolicy(Qt.NoFocus) self.__showHideButton.clicked.connect(self.__onShowHide) headerLayout = QHBoxLayout() headerLayout.setContentsMargins(0, 0, 0, 0) headerLayout.addSpacerItem(fixedSpacer) headerLayout.addWidget(self.__threadsLabel) headerLayout.addSpacerItem(expandingSpacer) headerLayout.addWidget(self.__showHideButton) self.headerFrame.setLayout(headerLayout) self.__threadsList = QTreeWidget() self.__threadsList.setSortingEnabled(False) # I might not need that because of two reasons: # - the window has no focus # - the window has custom current indicator # self.__threadsList.setAlternatingRowColors( True ) self.__threadsList.setRootIsDecorated(False) self.__threadsList.setItemsExpandable(False) self.__threadsList.setUniformRowHeights(True) self.__threadsList.setSelectionMode(QAbstractItemView.NoSelection) self.__threadsList.setSelectionBehavior(QAbstractItemView.SelectRows) self.__threadsList.setItemDelegate(NoOutlineHeightDelegate(4)) self.__threadsList.setFocusPolicy(Qt.NoFocus) self.__threadsList.itemClicked.connect(self.__onThreadClicked) self.__threadsList.setHeaderLabels(["", "Name", "State", "TID"]) verticalLayout.addWidget(self.headerFrame) verticalLayout.addWidget(self.__threadsList) return def __onShowHide(self, startup=False): " Triggered when show/hide button is clicked " if startup or self.__threadsList.isVisible(): self.__threadsList.setVisible(False) self.__showHideButton.setIcon(PixmapCache().getIcon('more.png')) self.__showHideButton.setToolTip("Show threads list") self.__minH = self.minimumHeight() self.__maxH = self.maximumHeight() self.setMinimumHeight(self.headerFrame.height()) self.setMaximumHeight(self.headerFrame.height()) Settings().showThreadViewer = False else: self.__threadsList.setVisible(True) self.__showHideButton.setIcon(PixmapCache().getIcon('less.png')) self.__showHideButton.setToolTip("Hide threads list") self.setMinimumHeight(self.__minH) self.setMaximumHeight(self.__maxH) Settings().showThreadViewer = True return def __resizeColumns(self): " Resize the files list columns " self.__threadsList.header().setStretchLastSection(True) self.__threadsList.header().resizeSections( QHeaderView.ResizeToContents) self.__threadsList.header().resizeSection(0, 22) self.__threadsList.header().setResizeMode(0, QHeaderView.Fixed) return def clear(self): " Clears the content " self.__threadsList.clear() self.__threadsLabel.setText("Threads") return def populate(self, currentThreadID, threadList): " Populates the thread list from the client " self.clear() for thread in threadList: if thread['broken']: state = "Waiting at breakpoint" else: state = "Running" item = ThreadItem(thread['id'], thread['name'], state) if thread['id'] == currentThreadID: item.setCurrent(True) self.__threadsList.addTopLevelItem(item) self.__resizeColumns() self.__threadsLabel.setText("Threads (total: " + str(len(threadList)) + ")") return def switchControl(self, isInIDE): " Switches the UI depending where the control flow is " self.__threadsList.setEnabled(isInIDE) return def __onThreadClicked(self, item, column): " Triggered when a thread is clicked " if item.isCurrent(): return for index in xrange(self.__threadsList.topLevelItemCount()): listItem = self.__threadsList.topLevelItem(index) if listItem.isCurrent(): listItem.setCurrent(False) break item.setCurrent(True) self.__debugger.remoteSetThread(item.getTID()) return
class Window(QMainWindow): def __init__(self): self.a = 0 QMainWindow.__init__(self) self.setWindowTitle("Explorador de archivos y carpetas") self.back_history = [] self.forward_history = [] self.back_button = QPushButton(self) self.back_button.setIcon(QIcon("images/back.png")) self.back_button.clicked.connect(self.back_clicked) self.back_button.setEnabled(False) self.forward_button = QPushButton(self) self.forward_button.setIcon(QIcon("images/forward.png")) self.forward_button.clicked.connect(self.forward_clicked) self.forward_button.setEnabled(False) self.up_button = QPushButton(self) self.up_button.setIcon(QIcon("images/up.png")) self.up_button.clicked.connect(self.up_button_clicked) self.address_edit = QLineEdit(self) self.refresh_button = QPushButton(self) self.refresh_button.setIcon(QIcon("images/update.png")) self.refresh_button.clicked.connect(self.refresh_button_clicked) self.toplayout = QHBoxLayout() self.toplayout.addWidget(self.back_button) self.toplayout.addWidget(self.forward_button) self.toplayout.addWidget(self.up_button) self.toplayout.addWidget(self.address_edit) self.toplayout.addWidget(self.refresh_button) self.main_tree = QTreeWidget(self) self.main_tree.setRootIsDecorated(False) self.main_tree.setHeaderLabels( ("Nombre", u"Fecha de modificación", u"Tamaño")) self.main_tree.itemDoubleClicked.connect(self.item_double_clicked) self.layout = QVBoxLayout() self.layout.addLayout(self.toplayout) self.layout.addWidget(self.main_tree) self.central_widget = QWidget(self) self.central_widget.setLayout(self.layout) self.setCentralWidget(self.central_widget) self.resize(800, 600) # Iniciar en el directorio actual. self.load_path(getcwd()) def back_clicked(self, checked): if self.back_history and len(self.back_history) > 1: # Obtener el último elemento. path = self.back_history[-2] self.forward_history.append(self.back_history[-1]) # Remover el directorio actual. del self.back_history[-1] self.load_path(path, False) def forward_clicked(self, checked): if self.forward_history: path = self.forward_history[-1] self.back_history.append(path) del self.forward_history[-1] self.load_path(path, False) def item_double_clicked(self, item, column): filepath = join(self.current_path, unicode(item.text(0))) if isdir(filepath): self.load_path(filepath) else: # Iniciar archivo con el programa predeterminado. #startfile(filepath) a = filepath parcial.ponfoto(a) #print self.a def up_button_clicked(self, checked): parent = dirname(self.current_path) if parent != self.current_path: self.load_path(parent) def load_path(self, path, use_history=True): # Obtener archivos y carpetas. items = listdir(unicode(path)) # Eliminar el contenido anterior. self.main_tree.clear() for i in items: # Omitir archivos ocultos. if i.startswith("."): continue filepath = join(path, i) # Obtener informacion del archivo. stats = stat(filepath) # Crear el control ítem. item_widget = QTreeWidgetItem( (i, strftime("%c", localtime(stats.st_mtime)).decode("utf-8"), size(stats.st_size) if isfile(filepath) else "")) # Establecer el ícono correspondiente. item_widget.setIcon( 0, QIcon("images/%s.png" % ("file" if isfile(filepath) else "folder"))) # Añadir elemento. self.main_tree.addTopLevelItem(item_widget) # Ajustar el tamaño de las columnas. for i in range(3): self.main_tree.resizeColumnToContents(i) self.current_path = path self.address_edit.setText(self.current_path) # Añadir al historial. if use_history: self.back_history.append(self.current_path) # Habilitar / dehabilitar botones del historial. if self.back_history and len(self.back_history) > 1: if not self.back_button.isEnabled(): self.back_button.setEnabled(True) else: if self.back_button.isEnabled(): self.forward_history = [] self.back_button.setEnabled(False) if self.forward_history: if not self.forward_button.isEnabled(): self.forward_button.setEnabled(True) else: if self.forward_button.isEnabled(): self.forward_button.setEnabled(False) def refresh_button_clicked(self, checked): self.load_path(self.current_path)
class ChooseSectionsPage(QIWizardPage): """ page to choose the sections that should be compared in the table """ def __init__(self, parent=None): super(ChooseSectionsPage, self).__init__(parent) self.selected_sections = [] # sections in the right tree self.sections = [] # all sections without the selected self.filtered_sections = [] # filtered sections without the selected self.initUI() def initUI(self): mainlayout = QVBoxLayout() # layout containing the treewidgets sectionlistlayout = QHBoxLayout() # layout for filter form filterbox = QGroupBox("Filter") self.LEsecname = QLineEdit() self.LEsectype = QLineEdit() self.LEpropname = QLineEdit() filterlayout = QGridLayout() filterlayout.addWidget(QLabel("Section Name"), 1, 0) filterlayout.addWidget(QLabel("Section Type"), 2, 0) filterlayout.addWidget(QLabel("Property Name"), 3, 0) filterlayout.addWidget(self.LEsecname, 1, 1) filterlayout.addWidget(self.LEsectype, 2, 1) filterlayout.addWidget(self.LEpropname, 3, 1) filterbox.setLayout(filterlayout) self.LEsecname.textChanged.connect(self.filterSections) self.LEsectype.textChanged.connect(self.filterSections) self.LEpropname.textChanged.connect(self.filterSections) # define layout for the trre-widgets containing the sections self.section_tree = QTreeWidget() self.section_tree.setColumnCount(2) self.section_tree.setHeaderLabels(["Name", "Path"]) self.section_tree.itemDoubleClicked.connect(self.toright) self.selection_tree = QTreeWidget() self.selection_tree.setColumnCount(2) self.selection_tree.setHeaderLabels(["Name", "Path"]) self.selection_tree.itemDoubleClicked.connect(self.toleft) self.selection_tree.setSelectionMode(3) self.section_tree.setSelectionMode(3) self.settings.register("selected_secs", self.selected_sections) # buttons to move items of the tree-widgets movebuttonlayout = QVBoxLayout() btn_right = QToolButton() btn_right.setArrowType(Qt.RightArrow) btn_right.clicked.connect(self.toright) btn_left = QToolButton() btn_left.setArrowType(Qt.LeftArrow) btn_left.clicked.connect(self.toleft) movebuttonlayout.addStretch(1) movebuttonlayout.addWidget(btn_right) movebuttonlayout.addSpacing(1) movebuttonlayout.addWidget(btn_left) movebuttonlayout.addStretch(1) sectionlistlayout.addWidget(self.section_tree) sectionlistlayout.addSpacing(1) sectionlistlayout.addLayout(movebuttonlayout) sectionlistlayout.addSpacing(1) sectionlistlayout.addWidget(self.selection_tree) mainlayout.addLayout(sectionlistlayout) self.selectallcb = QCheckBox('select all (Ctrl+A)') self.selectallcb.stateChanged.connect(self.selectall) mainlayout.addWidget(self.selectallcb) mainlayout.addWidget(filterbox) self.setTitle("Select Sections") self.setLayout(mainlayout) self.adjustSize() def initializePage(self): # load sections and properties from the selected file odmldoc = odml.tools.xmlparser.load(self.settings.get_object( "inputfilename")) for section in odmldoc.itersections(): self.sections.append([section.name, section.get_path(), [p.name for p in section.properties], section.type]) # fill tree widget with sections and properties for line in self.sections: parent = QTreeWidgetItem([line[0], line[1]]) for p in line[2]: QTreeWidgetItem(parent, [str(p)]) self.section_tree.addTopLevelItem(parent) self.filtered_sections = list(self.sections) self.setTitle("Choose Sections") self.setSubTitle("Choose the sections you want to compare") def _get_selected_rows(self, tree): """ function to determine the selected rows in a specified QTreeWidget """ rows = [] for index in tree.selectedIndexes(): if index.parent().row() is -1: rows.append(index.row()) else: # if a property is selected, the whole section containing this # property shall be moved rows.append(index.parent().row()) # sort rownumbers in descending order to prevent shifting when moving # the items return sorted(list(set(rows)), reverse=True) def toright(self): """ function to shift items from the left TreeWidget to the right """ rows = self._get_selected_rows(self.section_tree) for row in rows: self.selection_tree.addTopLevelItem( self.section_tree.takeTopLevelItem(row)) self.selected_sections.append(self.sections.pop( self.sections.index(self.filtered_sections[row]))) self.filtered_sections.pop(row) def toleft(self): """ function to shift items from the right TreeWidget to the left """ rows = self._get_selected_rows(self.selection_tree) for row in rows: self.section_tree.addTopLevelItem( self.selection_tree.takeTopLevelItem(row)) item = self.selected_sections.pop(row) self.sections.append(item) self.filtered_sections.append(item) def filterSections(self): # find sections that match the filter self.filtered_sections = [s for s in self.sections if str(self.LEsecname.text()) in s[0] and str(self.LEsectype.text()) in s[3] and any([str(self.LEpropname.text()) in p for p in s[2]])] # clear left treewidget self.section_tree.clear() # fill left treewidget with the filtered sections for line in self.filtered_sections: parent = QTreeWidgetItem([line[0], line[1]]) for p in line[2]: QTreeWidgetItem(parent, [p]) self.section_tree.addTopLevelItem(parent) def selectall(self): if self.selectallcb.isChecked(): self.section_tree.selectAll() else: self.section_tree.clearSelection() def validatePage(self): if not self.settings.get_object("selected_secs"): QMessageBox.warning(self, 'No sections chosen', 'You should choose at least two sections to be ' 'compared in the table.') return 0 return 1
class DBDatabasesWidget(QWidget): """Displays a list of Databases""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.db = None self.setWindowTitle("Databases") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setHeaderLabels(["Server", "User", ""]) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(False) self.tree.setColumnWidth(C.widget, 20) self.connect( self.tree, SIGNAL( 'itemSelectionChanged()' ), self.on_tree_selection_changed ) self.connect( self.tree, SIGNAL( 'itemDoubleClicked (QTreeWidgetItem *,int)' ), self.on_tree_double_clicked ) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def on_open_server(self, butt): self.emit(SIGNAL("open_server"), butt.property("server").toString()) def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.server, srv['server']) item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.widget, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers()
class MembersWidget(QWidget): def __init__(self, parent, logger): super(MembersWidget, self).__init__(parent) self.logger = logger layout = QVBoxLayout(self) layout.setSpacing(0) self.dropdown_members_dict = {} self.dropdown_members_model = DropdownModel(get_peers(), self.logger) self.dropdown_members = QComboBox(self) self.dropdown_members.setModel(self.dropdown_members_model) topLayout = QHBoxLayout() topLayout.setSpacing(10) topLayout.addWidget(self.dropdown_members, 1) self.requestLogsButton = QPushButton("Request Logfiles", self) topLayout.addWidget(self.requestLogsButton) layout.addLayout(topLayout) layout.addWidget(QLabel("Member Information:", self)) self.memberInformationTable = QTreeWidget(self) self.memberInformationTable.setMaximumHeight(65) self.memberInformationTable.setSelectionMode(QTreeWidget.NoSelection) layout.addWidget(self.memberInformationTable, 0) layout.addWidget(QLabel("Send Message:", self)) sendMessageLayout = QHBoxLayout() sendMessageLayout.setSpacing(10) messageInput = HistoryLineEdit(self, "Enter a message") self.sendMessageButton = QPushButton("Send", self) sendMessageLayout.addWidget(messageInput, 1) sendMessageLayout.addWidget(self.sendMessageButton) layout.addLayout(sendMessageLayout) layout.addWidget(QLabel("Log files:", self)) logSplitter = QSplitter(Qt.Horizontal, self) logListWidget = QWidget(self) logListLayout = QVBoxLayout(logListWidget) logListLayout.setContentsMargins(0, 0, 0, 0) self.log_tree_view = QTreeWidget(logSplitter) self.log_tree_view.setAlternatingRowColors(True) self.log_tree_view.setColumnCount(1) self.log_tree_view.setHeaderHidden(True) self.log_tree_view.setItemsExpandable(False) self.log_tree_view.setIndentation(0) logListLayout.addWidget(self.log_tree_view, 1) logListBottomLayout = QHBoxLayout() self.logSizeLabel = QLabel(logListWidget) logListBottomLayout.addWidget(self.logSizeLabel, 1) self.clearLogsButton = QPushButton("Clear", logListWidget) self.clearLogsButton.setEnabled(False) self.clearLogsButton.clicked.connect(self.clearLogs) logListBottomLayout.addWidget(self.clearLogsButton, 0) logListLayout.addLayout(logListBottomLayout) logSplitter.addWidget(logListWidget) self.log_area = QTextEdit(logListWidget) self.log_area.setLineWrapMode(QTextEdit.WidgetWidth) self.log_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.log_area.setReadOnly(True) logSplitter.addWidget(self.log_area) logSplitter.setStretchFactor(0, 0) logSplitter.setStretchFactor(1, 1) layout.addWidget(logSplitter, 1) self.memberSelectionChanged() self.log_tree_view.selectionModel().selectionChanged.connect(self.displaySelectedLogfile) self.dropdown_members.currentIndexChanged.connect(self.memberSelectionChanged) self.requestLogsButton.clicked.connect(self.requestLogClicked) self.sendMessageButton.clicked.connect(partial(self.sendMessageToMember, messageInput)) messageInput.returnPressed.connect(partial(self.sendMessageToMember, messageInput)) get_notification_center().connectPeerAppended(self.dropdown_members_model.externalRowAppended) get_notification_center().connectPeerUpdated(self.dropdown_members_model.externalRowUpdated) get_notification_center().connectPeerRemoved(self.dropdown_members_model.externalRowRemoved) get_notification_center().connectPeerUpdated(self.updateMemberInformation) def destroy_widget(self): get_notification_center().disconnectPeerAppended(self.dropdown_members_model.externalRowAppended) get_notification_center().disconnectPeerUpdated(self.dropdown_members_model.externalRowUpdated) get_notification_center().disconnectPeerRemoved(self.dropdown_members_model.externalRowRemoved) get_notification_center().disconnectPeerUpdated(self.updateMemberInformation) def listLogfiles(self, basePath, sort=None): if sort is None: sort = lambda aFile: -self.getLogNumber(aFile) logList = [ os.path.join(basePath, aFile) for aFile in os.listdir(basePath) if aFile.endswith(".log") and not os.path.isdir(os.path.join(basePath, aFile)) ] return sorted(logList, key=sort) def getNumLogsToKeep(self, oldLogFiles, newLogFiles, logOffset): oldestNew = None for aLogFile in newLogFiles: oldestNew, _ = self.getLogDates(aLogFile) if oldestNew != None: break if oldestNew == None: # new new log file contains timestamps (they are probably all empty) return len(oldLogFiles) numToKeep = 0 while numToKeep < len(oldLogFiles) - logOffset: curTime, _ = self.getLogDates(oldLogFiles[numToKeep]) if curTime == None or curTime < oldestNew: # keep empty log files numToKeep = numToKeep + 1 else: break return numToKeep def getLogDates(self, aLogFile): with codecs.open(aLogFile, "rb", "utf-8") as logContent: logLines = logContent.readlines() firstDate = None for aLine in logLines: firstDate = getLogLineTime(aLine) if firstDate != None: break lastDate = None for aLine in reversed(logLines): lastDate = getLogLineTime(aLine) if lastDate != None: break return firstDate, lastDate def getLogNumber(self, aLogFile): aLogFile = os.path.basename(aLogFile) try: return int(aLogFile[: aLogFile.rfind(".")]) except: return -1 def shiftLogFiles(self, oldLogFiles, numToKeep, shift, logOffset): renamedLogfiles = [] for index, aFile in enumerate(oldLogFiles): logNum = self.getLogNumber(aFile) if logNum < logOffset: # don't touch up-to-date logs break if index < numToKeep: newName = os.path.join(os.path.dirname(aFile), "%d.log" % (logNum + shift)) renamedLogfiles.append((len(oldLogFiles) - index - 1, aFile, newName)) os.rename(aFile, newName) else: os.remove(aFile) return renamedLogfiles def handleNewLogFiles(self, basePath, tmpPath, logOffset=0): oldLogFiles = self.listLogfiles(basePath) newLogFiles = self.listLogfiles(tmpPath) # check how many log files are actually new numToKeep = self.getNumLogsToKeep(oldLogFiles, newLogFiles, logOffset) # rename / remove old log files to make room for the new ones numNew = len(newLogFiles) - (len(oldLogFiles) - logOffset - numToKeep) renamedLogfiles = self.shiftLogFiles(oldLogFiles, numToKeep, numNew, logOffset) # move new log files addedLogfiles = [] for index, aLogFile in enumerate(reversed(newLogFiles)): shutil.move(aLogFile, basePath) if index < numNew: addedLogfiles.append((index + logOffset, os.path.join(basePath, os.path.basename(aLogFile)))) shutil.rmtree(tmpPath, True) return numNew, addedLogfiles, renamedLogfiles def requestFinished(self): self.requestLogsButton.setEnabled(True) self.dropdown_members.setEnabled(True) @loggingSlot(QThread, object) def cb_log_transfer_success(self, thread, path): path = convert_string(path) basePath = os.path.dirname(path) tmpPath = os.path.join(basePath, "tmp") if not os.path.exists(tmpPath): os.makedirs(tmpPath) logsAdded = [] if path.endswith(".tgz"): # extract received log files with contextlib.closing(tarfile.open(path, "r:gz")) as tarContent: tarContent.extractall(tmpPath) _, logsAdded, logsRenamed = self.handleNewLogFiles(basePath, tmpPath) self.requestFinished() else: # log comes from old version logNum = 0 if thread.sender in self.logRequests: logNum, requestTime = self.logRequests[thread.sender] now = datetime.now() td = now - requestTime tdSeconds = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 6 if tdSeconds > self.LOG_REQUEST_TIMEOUT: # request timed out or was finished already logNum = 0 shutil.move(path, os.path.join(tmpPath, "%d.log" % logNum)) numNew, logsAdded, logsRenamed = self.handleNewLogFiles(basePath, tmpPath, logNum) if numNew > 0 and logNum < 9: # there might be more new ones self.logRequests[thread.sender] = (logNum + 1, datetime.now()) self.logger.debug("log seems to be new, another!!!") logsAdded.append((logNum + 1, None)) self.request_log(thread.sender, logNum + 1) elif thread.sender in self.logRequests: # request finished del self.logRequests[thread.sender] self.requestFinished() else: self.requestFinished() if len(logsAdded) > 0 or len(logsRenamed) > 0: self.updateLogList(logsAdded, logsRenamed) @loggingSlot(QThread, object) def cb_log_transfer_error(self, _thread, message): if not self.isVisible(): return False self.log_area.setText("Error while getting log (%s)" % message) self.requestFinished() def get_selected_log_member(self): member = convert_string(self.dropdown_members.currentText()) if not member: return None if "(" in member: # member contains name, extract ID member = member[member.rfind("(") + 1 : member.rfind(")")] return member def request_log(self, member=None, logNum=0): if member == None: member = self.get_selected_log_member() if member != None: self.logger.debug("Requesting log %d from %s", logNum, member) get_server().call( "HELO_REQUEST_LOGFILE %s %d" % (DataReceiverThread.getOpenPort(category="log%s" % member), logNum), set([member]), ) else: self.log_area.setText("No Member selected!") @loggingSlot() def requestLogClicked(self): self.requestLogsButton.setEnabled(False) self.dropdown_members.setEnabled(False) self.updateLogList([(0, None)]) self.request_log() def listLogFilesForMember(self, member): if member is None: return [] logDir = os.path.join(get_settings().get_main_config_dir(), "logs", member) if not os.path.exists(logDir): return [] return self.listLogfiles(logDir) def numLogFilesForMember(self, member): return len(self.listLogFilesForMember(member)) def requestTimedOut(self, item): if not sip.isdeleted(item) and item != None and item.data(0, Qt.UserRole) == None: self.log_tree_view.takeTopLevelItem(self.log_tree_view.indexFromItem(item).row()) self.requestFinished() def formatFileSize(self, num): for x in ["Bytes", "KB", "MB", "GB", "TB"]: if num < 1024.0: return "%3.1f %s" % (num, x) num /= 1024.0 def initializeLogItem(self, item, logFile): firstDate, lastDate = self.getLogDates(logFile) text = None tooltip = None if firstDate != None: text = firstDate.strftime("%Y-%m-%d %H:%M:%S") tooltip = u"File: %s\nFirst entry: %s\nLast entry: %s" % ( logFile, firstDate.strftime("%Y-%m-%d %H:%M:%S"), lastDate.strftime("%Y-%m-%d %H:%M:%S"), ) else: timestamp = datetime.fromtimestamp(os.path.getmtime(logFile)).strftime("%Y-%m-%d %H:%M:%S") text = u"%s" % os.path.basename(logFile) tooltip = u"File:%s\nModification Date: %s" % (logFile, timestamp) text = text + "\n%s" % self.formatFileSize(os.path.getsize(logFile)) if tooltip != None: item.setData(0, Qt.ToolTipRole, QVariant(tooltip)) item.setData(0, Qt.UserRole, logFile) item.setData(0, Qt.DisplayRole, QVariant(text)) @loggingSlot() def clearLogs(self): for aLogFile in self.listLogFilesForMember(self.get_selected_log_member()): os.remove(aLogFile) self.updateLogList() def updateLogList(self, logsAdded=None, logsRenamed=None): selectedMember = self.get_selected_log_member() if logsAdded == None: self.log_tree_view.clear() logsAdded = [] for index, logFile in enumerate(reversed(self.listLogFilesForMember(selectedMember))): logsAdded.append((index, logFile)) if len(logsAdded) == 0: self.log_tree_view.clear() self.log_tree_view.addTopLevelItem( QTreeWidgetItem(self.log_tree_view, QStringList("No logs available.")) ) self.log_tree_view.setSelectionMode(QTreeWidget.NoSelection) self.logSizeLabel.setText("No logs") self.clearLogsButton.setEnabled(False) return if logsRenamed != None: for index, oldName, newName in logsRenamed: # index + 1 because of the "requesting" item item = self.log_tree_view.topLevelItem(index + 1) if item != None: itemLogFile = convert_string(item.data(0, Qt.UserRole).toString()) if itemLogFile != oldName: self.logger.warning( "index does not correspond to item in list:\n\t%s\n\t%s", itemLogFile, oldName ) self.initializeLogItem(item, newName) if len(logsAdded) == 0: self.log_tree_view.takeTopLevelItem(0) else: for index, logFile in logsAdded: oldItem = self.log_tree_view.topLevelItem(index) item = None if oldItem != None and oldItem.data(0, Qt.UserRole) == None: # requested item has been received item = oldItem else: item = QTreeWidgetItem() oldItem = None if logFile == None: item.setData(0, Qt.DisplayRole, QVariant("Requesting...")) QTimer.singleShot(6000, partial(self.requestTimedOut, item)) else: self.initializeLogItem(item, logFile) if oldItem == None: # else, the old item is being modified self.log_tree_view.insertTopLevelItem(index, item) self.log_tree_view.setSelectionMode(QTreeWidget.SingleSelection) totalSize = 0 for aLogFile in self.listLogFilesForMember(selectedMember): totalSize += os.path.getsize(aLogFile) self.logSizeLabel.setText("%s consumed" % self.formatFileSize(totalSize)) self.clearLogsButton.setEnabled(True) # self.displaySelectedLogfile() def getSelectedLogContent(self): member = self.get_selected_log_member() if member == None: return "No Log selected." selection = self.log_tree_view.selectedIndexes() if len(selection) is 0: return "No Log selected." logPath = convert_string(selection[0].data(Qt.UserRole).toString()) if logPath == None: return "ERROR: path is None" if not os.path.exists(logPath): return "File not found: " + logPath fcontent = "" try: with codecs.open(logPath, "r", "utf8") as fhandler: fcontent = fhandler.read() except Exception as e: self.logger.exception("Error reading file") fcontent = "Error reading file: %s" % str(e) return fcontent @loggingSlot(QItemSelection, QItemSelection) def displaySelectedLogfile(self, _new, _old): self.log_area.setText(self.getSelectedLogContent()) @loggingSlot(int) def memberSelectionChanged(self, _new=None): self.updateLogList() isMemberSelected = self.get_selected_log_member() != None self.sendMessageButton.setEnabled(isMemberSelected) self.requestLogsButton.setEnabled(isMemberSelected) self.updateMemberInformation() @loggingSlot(object) def sendMessageToMember(self, lineEdit): selectedMember = self.get_selected_log_member() if selectedMember != None: get_server().call(convert_string(lineEdit.text()), set([selectedMember])) lineEdit.clear() @loggingSlot(object, object) def updateMemberInformation(self, peerID=None, peerInfo=None): if peerID != None and peerID != self.get_selected_log_member(): # only update if selected member updated return self.memberInformationTable.clear() if self.get_selected_log_member() == None: self.memberInformationTable.setColumnCount(0) self.memberInformationTable.setHeaderLabel("No member selected.") return if peerInfo == None: peerInfo = get_peers().getPeerInfo(pID=self.get_selected_log_member()) if peerInfo == None: self.memberInformationTable.setColumnCount(0) self.memberInformationTable.setHeaderLabel("No member information available.") return self.memberInformationTable.setColumnCount(len(peerInfo)) headers = sorted(peerInfo.keys(), key=lambda s: s.lower()) self.memberInformationTable.setHeaderLabels(QStringList(headers)) item = QTreeWidgetItem(self.memberInformationTable) for col, header in enumerate(headers): item.setData(col, Qt.DisplayRole, QVariant(peerInfo[header])) for col in range(self.memberInformationTable.columnCount()): self.memberInformationTable.resizeColumnToContents(col)
class RecentProjectsViewer(QWidget): " Recent projects viewer implementation " def __init__(self, parent=None): QWidget.__init__(self, parent) self.__projectContextItem = None self.__fileContextItem = None self.upper = self.__createRecentFilesLayout() self.lower = self.__createRecentProjectsLayout() self.__createProjectPopupMenu() self.__createFilePopupMenu() layout = QVBoxLayout() layout.setContentsMargins(1, 1, 1, 1) splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.upper) splitter.addWidget(self.lower) splitter.setCollapsible(0, False) splitter.setCollapsible(1, False) layout.addWidget(splitter) self.setLayout(layout) self.__populateProjects() self.__populateFiles() self.__updateProjectToolbarButtons() self.__updateFileToolbarButtons() # Debugging mode support self.__debugMode = False parent.debugModeChanged.connect(self.__onDebugMode) return def setTooltips(self, switchOn): " Switches the tooltips mode " for index in xrange(0, self.recentFilesView.topLevelItemCount()): self.recentFilesView.topLevelItem(index).updateIconAndTooltip() for index in xrange(0, self.projectsView.topLevelItemCount()): self.projectsView.topLevelItem(index).updateTooltip() return def __createFilePopupMenu(self): " create the recent files popup menu " self.__fileMenu = QMenu(self.recentFilesView) self.__openMenuItem = self.__fileMenu.addAction( getIcon('openitem.png'), 'Open', self.__openFile) self.__copyPathFileMenuItem = self.__fileMenu.addAction( getIcon('copytoclipboard.png'), 'Copy path to clipboard', self.__filePathToClipboard) self.__fileMenu.addSeparator() self.__delFileMenuItem = self.__fileMenu.addAction( getIcon('trash.png'), 'Delete from recent', self.__deleteFile) self.recentFilesView.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self.recentFilesView, SIGNAL("customContextMenuRequested(const QPoint &)"), self.__handleShowFileContextMenu) self.connect(GlobalData().project, SIGNAL('recentFilesChanged'), self.__populateFiles) return def __createProjectPopupMenu(self): " Creates the recent project popup menu " self.__projectMenu = QMenu(self.projectsView) self.__prjLoadMenuItem = self.__projectMenu.addAction( getIcon('load.png'), 'Load', self.__loadProject) self.__projectMenu.addSeparator() self.__propsMenuItem = self.__projectMenu.addAction( getIcon('smalli.png'), 'Properties', self.__viewProperties) self.__prjCopyPathMenuItem = self.__projectMenu.addAction( getIcon('copytoclipboard.png'), 'Copy path to clipboard', self.__prjPathToClipboard) self.__projectMenu.addSeparator() self.__delPrjMenuItem = self.__projectMenu.addAction( getIcon('trash.png'), 'Delete from recent', self.__deleteProject) self.projectsView.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self.projectsView, SIGNAL("customContextMenuRequested(const QPoint &)"), self.__handleShowPrjContextMenu) Settings().recentListChanged.connect(self.__populateProjects) GlobalData().project.projectChanged.connect(self.__projectChanged) return def __createRecentFilesLayout(self): " Creates the upper part - recent files " headerFrame = QFrame() headerFrame.setFrameStyle(QFrame.StyledPanel) headerFrame.setAutoFillBackground(True) headerPalette = headerFrame.palette() headerBackground = headerPalette.color(QPalette.Background) headerBackground.setRgb(min(headerBackground.red() + 30, 255), min(headerBackground.green() + 30, 255), min(headerBackground.blue() + 30, 255)) headerPalette.setColor(QPalette.Background, headerBackground) headerFrame.setPalette(headerPalette) headerFrame.setFixedHeight(24) recentFilesLabel = QLabel() recentFilesLabel.setText("Recent files") headerLayout = QHBoxLayout() headerLayout.setContentsMargins(3, 0, 0, 0) headerLayout.addWidget(recentFilesLabel) headerFrame.setLayout(headerLayout) self.recentFilesView = QTreeWidget() self.recentFilesView.setAlternatingRowColors(True) self.recentFilesView.setRootIsDecorated(False) self.recentFilesView.setItemsExpandable(False) self.recentFilesView.setSortingEnabled(True) self.recentFilesView.setItemDelegate(NoOutlineHeightDelegate(4)) self.recentFilesView.setUniformRowHeights(True) self.__filesHeaderItem = QTreeWidgetItem(["", "File", "Absolute path"]) self.recentFilesView.setHeaderItem(self.__filesHeaderItem) self.recentFilesView.header().setSortIndicator(1, Qt.AscendingOrder) self.connect(self.recentFilesView, SIGNAL("itemSelectionChanged()"), self.__fileSelectionChanged) self.connect(self.recentFilesView, SIGNAL("itemActivated(QTreeWidgetItem *, int)"), self.__fileActivated) # Toolbar part - buttons self.openFileButton = QAction(getIcon('openitem.png'), 'Open the highlighted file', self) self.connect(self.openFileButton, SIGNAL("triggered()"), self.__openFile) self.copyFilePathButton = QAction(getIcon('copytoclipboard.png'), 'Copy path to clipboard', self) self.connect(self.copyFilePathButton, SIGNAL("triggered()"), self.__filePathToClipboard) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.trashFileButton = QAction(getIcon('delitem.png'), 'Remove selected (not from the disk)', self) self.connect(self.trashFileButton, SIGNAL("triggered()"), self.__deleteFile) self.upperToolbar = QToolBar() self.upperToolbar.setMovable(False) self.upperToolbar.setAllowedAreas(Qt.TopToolBarArea) self.upperToolbar.setIconSize(QSize(16, 16)) self.upperToolbar.setFixedHeight(28) self.upperToolbar.setContentsMargins(0, 0, 0, 0) self.upperToolbar.addAction(self.openFileButton) self.upperToolbar.addAction(self.copyFilePathButton) self.upperToolbar.addWidget(spacer) self.upperToolbar.addAction(self.trashFileButton) recentFilesLayout = QVBoxLayout() recentFilesLayout.setContentsMargins(0, 0, 0, 0) recentFilesLayout.setSpacing(0) recentFilesLayout.addWidget(headerFrame) recentFilesLayout.addWidget(self.upperToolbar) recentFilesLayout.addWidget(self.recentFilesView) upperContainer = QWidget() upperContainer.setContentsMargins(0, 0, 0, 0) upperContainer.setLayout(recentFilesLayout) return upperContainer def getRecentFilesToolbar(self): " Provides a reference to the recent files toolbar " return self.upperToolbar def __createRecentProjectsLayout(self): " Creates the bottom layout " self.headerFrame = QFrame() self.headerFrame.setFrameStyle(QFrame.StyledPanel) self.headerFrame.setAutoFillBackground(True) headerPalette = self.headerFrame.palette() headerBackground = headerPalette.color(QPalette.Background) headerBackground.setRgb(min(headerBackground.red() + 30, 255), min(headerBackground.green() + 30, 255), min(headerBackground.blue() + 30, 255)) headerPalette.setColor(QPalette.Background, headerBackground) self.headerFrame.setPalette(headerPalette) self.headerFrame.setFixedHeight(24) recentProjectsLabel = QLabel() recentProjectsLabel.setText("Recent projects") expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding) self.__showHideButton = QToolButton() self.__showHideButton.setAutoRaise(True) self.__showHideButton.setIcon(getIcon('less.png')) self.__showHideButton.setFixedSize(20, 20) self.__showHideButton.setToolTip("Hide recent projects list") self.__showHideButton.setFocusPolicy(Qt.NoFocus) self.connect(self.__showHideButton, SIGNAL('clicked()'), self.__onShowHide) headerLayout = QHBoxLayout() headerLayout.setContentsMargins(3, 0, 0, 0) headerLayout.addWidget(recentProjectsLabel) headerLayout.addSpacerItem(expandingSpacer) headerLayout.addWidget(self.__showHideButton) self.headerFrame.setLayout(headerLayout) # Toolbar part - buttons self.loadButton = QAction(getIcon('load.png'), 'Load the highlighted project', self) self.connect(self.loadButton, SIGNAL("triggered()"), self.__loadProject) self.propertiesButton = QAction( getIcon('smalli.png'), 'Show the highlighted project ' 'properties', self) self.connect(self.propertiesButton, SIGNAL("triggered()"), self.__viewProperties) self.copyPrjPathButton = QAction(getIcon('copytoclipboard.png'), 'Copy path to clipboard', self) self.connect(self.copyPrjPathButton, SIGNAL("triggered()"), self.__prjPathToClipboard) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.trashButton = QAction(getIcon('delitem.png'), 'Remove selected (not from the disk)', self) self.connect(self.trashButton, SIGNAL("triggered()"), self.__deleteProject) self.lowerToolbar = QToolBar() self.lowerToolbar.setMovable(False) self.lowerToolbar.setAllowedAreas(Qt.TopToolBarArea) self.lowerToolbar.setIconSize(QSize(16, 16)) self.lowerToolbar.setFixedHeight(28) self.lowerToolbar.setContentsMargins(0, 0, 0, 0) self.lowerToolbar.addAction(self.loadButton) self.lowerToolbar.addAction(self.propertiesButton) self.lowerToolbar.addAction(self.copyPrjPathButton) self.lowerToolbar.addWidget(spacer) self.lowerToolbar.addAction(self.trashButton) self.projectsView = QTreeWidget() self.projectsView.setAlternatingRowColors(True) self.projectsView.setRootIsDecorated(False) self.projectsView.setItemsExpandable(False) self.projectsView.setSortingEnabled(True) self.projectsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.projectsView.setUniformRowHeights(True) self.__projectsHeaderItem = QTreeWidgetItem( ["", "Project", "Absolute path"]) self.projectsView.setHeaderItem(self.__projectsHeaderItem) self.projectsView.header().setSortIndicator(1, Qt.AscendingOrder) self.connect(self.projectsView, SIGNAL("itemActivated(QTreeWidgetItem *, int)"), self.__projectActivated) self.connect(self.projectsView, SIGNAL("itemSelectionChanged()"), self.__projectSelectionChanged) recentProjectsLayout = QVBoxLayout() recentProjectsLayout.setContentsMargins(0, 0, 0, 0) recentProjectsLayout.setSpacing(0) recentProjectsLayout.addWidget(self.headerFrame) recentProjectsLayout.addWidget(self.lowerToolbar) recentProjectsLayout.addWidget(self.projectsView) lowerContainer = QWidget() lowerContainer.setContentsMargins(0, 0, 0, 0) lowerContainer.setLayout(recentProjectsLayout) return lowerContainer def getRecentProjectsToolbar(self): " Provides a reference to the projects toolbar " return self.lowerToolbar def __projectSelectionChanged(self): " Handles the projects changed selection " selected = list(self.projectsView.selectedItems()) if selected: self.__projectContextItem = selected[0] else: self.__projectContextItem = None self.__updateProjectToolbarButtons() return def __fileSelectionChanged(self): " Handles the files changed selection " selected = list(self.recentFilesView.selectedItems()) if selected: self.__fileContextItem = selected[0] else: self.__fileContextItem = None self.__updateFileToolbarButtons() return def __updateProjectToolbarButtons(self): " Updates the toolbar buttons depending on the __projectContextItem " if self.__projectContextItem is None: self.loadButton.setEnabled(False) self.propertiesButton.setEnabled(False) self.copyPrjPathButton.setEnabled(False) self.trashButton.setEnabled(False) else: enabled = self.__projectContextItem.isValid() isCurrentProject = self.__projectContextItem.isCurrent() self.propertiesButton.setEnabled(enabled) self.copyPrjPathButton.setEnabled(True) self.loadButton.setEnabled(enabled and not isCurrentProject and not self.__debugMode) self.trashButton.setEnabled(not isCurrentProject) return def __updateFileToolbarButtons(self): " Updates the toolbar buttons depending on the __fileContextItem " enabled = self.__fileContextItem is not None self.openFileButton.setEnabled(enabled) self.copyFilePathButton.setEnabled(enabled) self.trashFileButton.setEnabled(enabled) return def __handleShowPrjContextMenu(self, coord): " Show the project item context menu " self.__projectContextItem = self.projectsView.itemAt(coord) if self.__projectContextItem is None: return enabled = self.__projectContextItem.isValid() isCurrentProject = self.__projectContextItem.isCurrent() self.__propsMenuItem.setEnabled(enabled) self.__delPrjMenuItem.setEnabled(not isCurrentProject) # fName = self.__projectContextItem.getFilename() self.__prjLoadMenuItem.setEnabled(enabled and not isCurrentProject and not self.__debugMode) self.__projectMenu.popup(QCursor.pos()) return def __sortProjects(self): " Sort the project items " self.projectsView.sortItems( \ self.projectsView.sortColumn(), self.projectsView.header().sortIndicatorOrder() ) return def __sortFiles(self): " Sort the file items " self.recentFilesView.sortItems( self.recentFilesView.sortColumn(), self.recentFilesView.header().sortIndicatorOrder()) return def __resizeProjectColumns(self): """ Resize the projects list columns """ self.projectsView.header().setStretchLastSection(True) self.projectsView.header().resizeSections(QHeaderView.ResizeToContents) self.projectsView.header().resizeSection(0, 22) self.projectsView.header().setResizeMode(0, QHeaderView.Fixed) return def __resizeFileColumns(self): " Resize the files list columns " self.recentFilesView.header().setStretchLastSection(True) self.recentFilesView.header().resizeSections( QHeaderView.ResizeToContents) self.recentFilesView.header().resizeSection(0, 22) self.recentFilesView.header().setResizeMode(0, QHeaderView.Fixed) return def __projectActivated(self, item, column): " Handles the double click (or Enter) on the item " self.__projectContextItem = item self.__loadProject() return def __fileActivated(self, item, column): " Handles the double click (or Enter) on a file item " self.__fileContextItem = item self.__openFile() return def __viewProperties(self): " Handles the 'view properties' context menu item " if self.__projectContextItem is None: return if not self.__projectContextItem.isValid(): return if self.__projectContextItem.isCurrent(): # This is the current project - it can be edited project = GlobalData().project dialog = ProjectPropertiesDialog(project, self) if dialog.exec_() == QDialog.Accepted: importDirs = [] for index in xrange(dialog.importDirList.count()): importDirs.append(dialog.importDirList.item(index).text()) scriptName = dialog.scriptEdit.text().strip() relativePath = relpath(scriptName, project.getProjectDir()) if not relativePath.startswith('..'): scriptName = relativePath project.updateProperties( scriptName, importDirs, dialog.creationDateEdit.text().strip(), dialog.authorEdit.text().strip(), dialog.licenseEdit.text().strip(), dialog.copyrightEdit.text().strip(), dialog.versionEdit.text().strip(), dialog.emailEdit.text().strip(), dialog.descriptionEdit.toPlainText().strip()) else: # This is not the current project - it can be viewed fName = self.__projectContextItem.getFilename() dialog = ProjectPropertiesDialog(fName, self) dialog.exec_() return def __deleteProject(self): " Handles the 'delete from recent' context menu item " if self.__projectContextItem is None: return # Removal from the visible list is done via a signal which comes back # from settings fName = self.__projectContextItem.getFilename() Settings().deleteRecentProject(fName) return def __loadProject(self): " handles 'Load' context menu item " if self.__projectContextItem is None: return if not self.__projectContextItem.isValid(): return if self.__debugMode: return projectFileName = self.__projectContextItem.getFilename() if self.__projectContextItem.isCurrent(): GlobalData().mainWindow.openFile(projectFileName, -1) return # This is the current project, open for text editing QApplication.processEvents() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) if os.path.exists(projectFileName): mainWin = GlobalData().mainWindow editorsManager = mainWin.editorsManagerWidget.editorsManager if editorsManager.closeRequest(): prj = GlobalData().project prj.setTabsStatus(editorsManager.getTabsStatus()) editorsManager.closeAll() prj.loadProject(projectFileName) mainWin.activateProjectTab() else: logging.error("The project " + os.path.basename(projectFileName) + " disappeared from the file system.") self.__populateProjects() QApplication.restoreOverrideCursor() return def __populateProjects(self): " Populates the recent projects " self.projectsView.clear() for item in Settings().recentProjects: self.projectsView.addTopLevelItem(RecentProjectViewItem(item)) self.__sortProjects() self.__resizeProjectColumns() self.__updateProjectToolbarButtons() return def __populateFiles(self): " Populates the recent files " self.recentFilesView.clear() for path in GlobalData().project.recentFiles: self.recentFilesView.addTopLevelItem(RecentFileViewItem(path)) self.__sortFiles() self.__resizeFileColumns() self.__updateFileToolbarButtons() return def __projectChanged(self, what): " Triggered when the current project is changed " if what == CodimensionProject.CompleteProject: self.__populateProjects() self.__populateFiles() return if what == CodimensionProject.Properties: # Update the corresponding tooltip items = self.projectsView.findItems(GlobalData().project.fileName, Qt.MatchExactly, 2) if len(items) != 1: logging.error("Unexpected number of matched projects: " + str(len(items))) return items[0].updateTooltip() return def __openFile(self): " Handles 'open' file menu item " self.__fileContextItem.updateIconAndTooltip() fName = self.__fileContextItem.getFilename() if not self.__fileContextItem.isValid(): logging.warning("Cannot open " + fName) return fileType = detectFileType(fName) if fileType == PixmapFileType: GlobalData().mainWindow.openPixmapFile(fName) return GlobalData().mainWindow.openFile(fName, -1) return def __deleteFile(self): " Handles 'delete from recent' file menu item " self.removeRecentFile(self.__fileContextItem.getFilename()) return def __handleShowFileContextMenu(self, coord): " File context menu " self.__fileContextItem = self.recentFilesView.itemAt(coord) if self.__fileContextItem is not None: self.__fileMenu.popup(QCursor.pos()) return def __filePathToClipboard(self): " Copies the file item path to the clipboard " if self.__fileContextItem is not None: QApplication.clipboard().setText( self.__fileContextItem.getFilename()) return def __prjPathToClipboard(self): " Copies the project item path to the clipboard " if self.__projectContextItem is not None: QApplication.clipboard().setText( self.__projectContextItem.getFilename()) return def onFileUpdated(self, fileName, uuid): " Triggered when the file is updated: python or project " realPath = os.path.realpath(fileName) count = self.recentFilesView.topLevelItemCount() for index in xrange(0, count): item = self.recentFilesView.topLevelItem(index) itemRealPath = os.path.realpath(item.getFilename()) if realPath == itemRealPath: item.updateIconAndTooltip() break for index in xrange(0, self.projectsView.topLevelItemCount()): item = self.projectsView.topLevelItem(index) itemRealPath = os.path.realpath(item.getFilename()) if realPath == itemRealPath: item.updateTooltip() break return def __onShowHide(self): " Triggered when show/hide button is clicked " if self.projectsView.isVisible(): self.projectsView.setVisible(False) self.lowerToolbar.setVisible(False) self.__showHideButton.setIcon(getIcon('more.png')) self.__showHideButton.setToolTip("Show recent projects list") self.__minH = self.lower.minimumHeight() self.__maxH = self.lower.maximumHeight() self.lower.setMinimumHeight(self.headerFrame.height()) self.lower.setMaximumHeight(self.headerFrame.height()) else: self.projectsView.setVisible(True) self.lowerToolbar.setVisible(True) self.__showHideButton.setIcon(getIcon('less.png')) self.__showHideButton.setToolTip("Hide recent projects list") self.lower.setMinimumHeight(self.__minH) self.lower.setMaximumHeight(self.__maxH) return def __onDebugMode(self, newState): " Triggered when debug mode has changed " self.__debugMode = newState # Disable the load project button self.__updateProjectToolbarButtons() return def removeRecentFile(self, fName): " Removes a single file from the recent files list " GlobalData().project.removeRecentFile(fName) for index in xrange(self.recentFilesView.topLevelItemCount()): candidate = self.recentFilesView.topLevelItem(index) if candidate.getFilename() == fName: self.recentFilesView.takeTopLevelItem(index) return return
class VersionSelectDialog( QDialog ): def __init__( self, parent ): # initialize the super class super( VersionSelectDialog, self ).__init__( parent ) # create the tree self.uiVersionsTREE = QTreeWidget(self) self.uiVersionsTREE.setAlternatingRowColors(True) self.uiVersionsTREE.setRootIsDecorated(False) self.uiVersionsTREE.setSelectionMode( self.uiVersionsTREE.NoSelection ) header = self.uiVersionsTREE.header() header.setVisible(False) # create the layout layout = QVBoxLayout() layout.addWidget(self.uiVersionsTREE) layout.setContentsMargins(0,0,0,0) # inherit the highlight palette palette = self.palette() palette.setColor(palette.Highlight,parent.palette().color(palette.Highlight)) self.setPalette(palette) # set dialog information self.setLayout(layout) self.setWindowFlags( Qt.Popup ) self.resize(500,250) # create connections self.uiVersionsTREE.itemClicked.connect( self.acceptItem ) def closeEvent( self, event ): # update all the items for this for i in range( self.uiVersionsTREE.topLevelItemCount() ): item = self.uiVersionsTREE.topLevelItem(i) widget = item.versionWidget() version = widget.version() # match the active state version.setActive(widget.isActive()) super(VersionSelectDialog,self).closeEvent(event) def acceptItem( self, item ): # handle version change information widget = item.versionWidget() widget.toggleActive() # accept the dialog self.close() def popup( self, versions ): self.uiVersionsTREE.setUpdatesEnabled(False) self.uiVersionsTREE.blockSignals(True) self.uiVersionsTREE.clear() for version in versions: item = VersionItem(self.uiVersionsTREE, version) self.uiVersionsTREE.addTopLevelItem( item ) self.uiVersionsTREE.setItemWidget( item, 0, item.versionWidget() ) # reset the scrolling self.uiVersionsTREE.verticalScrollBar().setValue(0) self.uiVersionsTREE.setUpdatesEnabled(True) self.uiVersionsTREE.blockSignals(False) return self.exec_()
class PluginsDialog( QDialog ): " Codimension plugins dialog " def __init__( self, pluginManager, parent = None ): QDialog.__init__( self, parent ) self.setWindowTitle( "Plugin Manager" ) self.__pluginManager = pluginManager self.__configFuncs = {} # int -> callable self.__createLayout() self.__populate() self.__pluginsView.setFocus() self.__inItemChange = False return def __createLayout( self ): " Creates the dialog layout " self.resize( 640, 480 ) self.setSizeGripEnabled( True ) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors( True ) self.__pluginsView.setRootIsDecorated( False ) self.__pluginsView.setItemsExpandable( False ) self.__pluginsView.setSortingEnabled( True ) self.__pluginsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__pluginsView.setUniformRowHeights( True ) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( [ "", "", "", "Name", "Version", "" ] ) self.__pluginsView.setHeaderItem( self.__pluginsHeader ) self.__pluginsView.header().setSortIndicator( NAME_COL, Qt.AscendingOrder ) self.connect( self.__pluginsView, SIGNAL( "itemSelectionChanged()" ), self.__pluginSelectionChanged ) self.connect( self.__pluginsView, SIGNAL( "itemChanged(QTreeWidgetItem*,int)" ), self.__onItemChanged ) layout.addWidget( self.__pluginsView ) # Detailed information detailsLabel = QLabel( "Detailed information" ) layout.addWidget( detailsLabel ) self.__details = QTreeWidget() self.__details.setAlternatingRowColors( False ) self.__details.setRootIsDecorated( False ) self.__details.setItemsExpandable( False ) self.__details.setSortingEnabled( False ) self.__details.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__details.setUniformRowHeights( True ) detailsHeader = QTreeWidgetItem( [ "", "" ] ) self.__details.setHeaderItem( detailsHeader ) self.__details.setHeaderHidden( True ) metrics = QFontMetrics( self.__details.font() ) rect = metrics.boundingRect( "X" ) self.__details.setFixedHeight( rect.height() * 6 + 5 ) layout.addWidget( self.__details ) # Errors/warnings errorsLabel = QLabel( "Errors / warnings" ) layout.addWidget( errorsLabel ) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly( True ) self.__errorsText.setAcceptRichText( False ) metrics = QFontMetrics( self.__errorsText.font() ) rect = metrics.boundingRect( "X" ) self.__errorsText.setFixedHeight( rect.height() * 4 + 5 ) layout.addWidget( self.__errorsText ) # Buttons box buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Ok ) self.__OKButton = buttonBox.button( QDialogButtonBox.Ok ) self.__OKButton.setDefault( True ) self.connect( buttonBox, SIGNAL( "accepted()" ), self.close ) self.connect( buttonBox, SIGNAL( "rejected()" ), self.close ) layout.addWidget( buttonBox ) self.setLayout( layout ) return def __createConfigButton( self ): " Creates a configure button for a plugin " button = SettingsButton() self.connect( button, SIGNAL( 'CustomClick' ), self.onPluginSettings ) return button def __populate( self ): " Populates the list with the plugins " index = 0 for category in self.__pluginManager.activePlugins: for cdmPlugin in self.__pluginManager.activePlugins[ category ]: newItem = PluginItem( self.__pluginManager, cdmPlugin, True, category ) self.__pluginsView.addTopLevelItem( newItem ) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring" ) settingsButton.setEnabled( False ) else: settingsButton.setToolTip( "Click to configure" ) settingsButton.setEnabled( True ) self.__configFuncs[ index ] = configFunction settingsButton.index = index index += 1 except Exception: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received." ) settingsButton.setEnabled( False ) self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton ) for category in self.__pluginManager.inactivePlugins: for cdmPlugin in self.__pluginManager.inactivePlugins[ category ]: newItem = PluginItem( self.__pluginManager, cdmPlugin, False, category ) self.__pluginsView.addTopLevelItem( newItem ) settingsButton = self.__createConfigButton() try: configFunction = cdmPlugin.getObject().getConfigFunction() if configFunction is None: settingsButton.setToolTip( "Plugin does not need configuring" ) settingsButton.setEnabled( False ) else: settingsButton.setToolTip( "Enable plugin and then click to configure" ) settingsButton.setEnabled( False ) self.__configFuncs[ index ] = configFunction settingsButton.index = index index += 1 except: settingsButton.setToolTip( "Bad plugin interface. No " "configuration function received." ) settingsButton.setEnabled( False ) self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton ) for cdmPlugin in self.__pluginManager.unknownPlugins: newItem = PluginItem( self.__pluginManager, cdmPlugin, False, None ) self.__pluginsView.addTopLevelItem( newItem ) settingsButton = self.__createConfigButton() settingsButton.setToolTip( "Unknown plugins are not configurable" ) settingsButton.setEnabled( False ) self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton ) self.__sortPlugins() self.__resizePlugins() return def __sortPlugins( self ): " Sorts the plugins table " self.__pluginsView.sortItems( self.__pluginsView.sortColumn(), self.__pluginsView.header().sortIndicatorOrder() ) return def __resizePlugins( self ): " Resizes the plugins table " self.__pluginsView.header().setStretchLastSection( False ) self.__pluginsView.header().resizeSections( QHeaderView.ResizeToContents ) self.__pluginsView.header().resizeSection( STATE_COL, 28 ) self.__pluginsView.header().setResizeMode( STATE_COL, QHeaderView.Fixed ) self.__pluginsView.header().resizeSection( CONFLICT_COL, 28 ) self.__pluginsView.header().setResizeMode( CONFLICT_COL, QHeaderView.Fixed ) self.__pluginsView.header().resizeSection( TYPE_COL, 28 ) self.__pluginsView.header().setResizeMode( TYPE_COL, QHeaderView.Fixed ) self.__pluginsView.header().setResizeMode( VERSION_COL, QHeaderView.Stretch ) self.__pluginsView.header().resizeSection( SETTINGS_COL, 24 ) self.__pluginsView.header().setResizeMode( SETTINGS_COL, QHeaderView.Fixed ) return def __pluginSelectionChanged( self ): " Triggered when an item is selected " selected = list( self.__pluginsView.selectedItems() ) if selected: self.__updateDetails( selected[ 0 ] ) else: self.__updateDetails( None ) return def __updateDetails( self, item ): " Updates the content of the details and the error boxes " self.__details.clear() self.__errorsText.setText( "" ) if item is None: return self.__details.addTopLevelItem( QTreeWidgetItem( [ "Author", item.plugin.getAuthor() ] ) ) self.__details.addTopLevelItem( QTreeWidgetItem( [ "Path", os.path.normpath( item.plugin.getPath() ) ] ) ) self.__details.addTopLevelItem( QTreeWidgetItem( [ "Description", item.plugin.getDescription() ] ) ) self.__details.addTopLevelItem( QTreeWidgetItem( [ "Web site", item.plugin.getWebsite() ] ) ) copyright = item.plugin.getCopyright() if copyright is not None: if copyright.lower() != "unknown": self.__details.addTopLevelItem( QTreeWidgetItem( [ "Copyright", copyright ] ) ) for name in item.plugin.getDetails(): value = item.plugin.getDetails()[ name ] self.__details.addTopLevelItem( QTreeWidgetItem( [ name, value ] ) ) self.__errorsText.setText( item.plugin.conflictMessage ) return def __onItemChanged( self, item, column ): " Triggered when an item is changed " if self.__inItemChange: return if item.active: self.__inItemChange = True item.plugin.disable() item.active = False settingsButton = self.__pluginsView.itemWidget( item, SETTINGS_COL ) settingsButton.setEnabled( False ) if settingsButton.index != -1: settingsButton.setToolTip( "Enable plugin and then click to configure" ) if item.category in self.__pluginManager.inactivePlugins: self.__pluginManager.inactivePlugins[ item.category ].append( item.plugin ) else: self.__pluginManager.inactivePlugins[ item.category ] = [ item.plugin ] self.__pluginManager.activePlugins[ item.category ].remove( item.plugin ) self.__pluginManager.saveDisabledPlugins() self.__inItemChange = False self.__pluginManager.sendPluginDeactivated( item.plugin ) return self.__inItemChange = True message = self.__pluginManager.checkConflict( item.plugin ) if message is not None: item.setCheckState( STATE_COL, Qt.Unchecked ) self.__errorsText.setText( message ) self.__inItemChange = False return try: item.plugin.enable() item.active = True if item.category in self.__pluginManager.activePlugins: self.__pluginManager.activePlugins[ item.category ].append( item.plugin ) else: self.__pluginManager.activePlugins[ item.category ] = [ item.plugin ] self.__pluginManager.inactivePlugins[ item.category ].remove( item.plugin ) self.__pluginManager.saveDisabledPlugins() self.__errorsText.setText( "" ) item.setIcon( CONFLICT_COL, PixmapCache().getIcon( 'empty.png' ) ) item.setToolTip( CONFLICT_COL, "" ) settingsButton = self.__pluginsView.itemWidget( item, SETTINGS_COL ) if settingsButton.index != -1: settingsButton.setToolTip( "Click to configure" ) settingsButton.setEnabled( True ) self.__pluginManager.sendPluginActivated( item.plugin ) except: item.setCheckState( STATE_COL, Qt.Unchecked ) self.__errorsText.setText( "Error activating the plugin - exception is generated" ) self.__inItemChange = False return def onPluginSettings( self, index ): " Triggered when a configuring function is called " if index not in self.__configFuncs: return try: self.__configFuncs[ index ]() except Exception, exc: logging.error( "Error calling the plugin configuration function. " "Message: " + str( exc ) ) return
class Shortcuts(preferences.Page): def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton( icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager( win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = list(allactions.keys()) def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelerator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0) def items(self): """Yield all the items in the actions tree.""" def children(item): for i in range(item.childCount()): c = item.child(i) if c.childCount(): for c1 in children(c): yield c1 else: yield c for c in children(self.tree.invisibleRootItem()): yield c def item(self, collection, name): for item in self.items(): if item.collection.name == collection and item.name == name: return item def saveSettings(self): self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts") for item in self.items(): for scheme in self.scheme.schemes(): item.save(scheme) item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def loadSettings(self): self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes") # clear the settings in all the items for item in self.items(): item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def slotSchemeChanged(self): """Called when the Scheme combobox is changed by the user.""" for item in self.items(): item.switchScheme(self.scheme.currentScheme()) def slotCurrentItemChanged(self, item): if isinstance(item, ShortcutItem): self.edit.setText( _("&Edit Shortcut for \"{name}\"").format(name=item.text(0))) self.edit.setEnabled(True) global _lastaction _lastaction = item.name else: self.edit.setText(_("(no shortcut)")) self.edit.setEnabled(False) def import_(self, filename): from . import import_export import_export.importShortcut(filename, self, self.scheme) def export(self, name, filename): from . import import_export try: import_export.exportShortcut(self, self.scheme.currentScheme(), name, filename) except (IOError, OSError) as e: QMessageBox.critical( self, _("Error"), _("Can't write to destination:\n\n{url}\n\n{error}").format( url=filename, error=e.strerror)) def findShortcutConflict(self, shortcut): """Find the possible shortcut conflict and return the conflict name.""" if shortcut: item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return None scheme = self.scheme.currentScheme() for i in self.items(): a = i.action(scheme) if i != item and a.shortcuts(): for s1 in a.shortcuts(): if s1.matches(shortcut) or shortcut.matches(s1): return qutil.removeAccelerator(a.text()) return None def editCurrentItem(self): item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return dlg = ShortcutEditDialog(self, self.findShortcutConflict) scheme = self.scheme.currentScheme() action = item.action(scheme) default = item.defaultShortcuts() or None if dlg.editAction(action, default): shortcuts = action.shortcuts() # check for conflicts conflicting = [] for i in self.items(): if i is not item: for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts): if s1.matches(s2) or s2.matches(s1): conflicting.append(i) if conflicting: for i in conflicting: l = i.shortcuts(scheme) for s1 in list(l): # copy for s2 in shortcuts: if s1.matches(s2) or s2.matches(s1): l.remove(s1) i.setShortcuts(l, scheme) # store the shortcut item.setShortcuts(shortcuts, scheme) self.changed.emit()
def __addSimilarity( self, similarity, titleText ): " Adds a similarity " # Label title = QLabel( titleText ) title.setFont( self.__headerFont ) self.__vLayout.addWidget( title ) self.__widgets.append( title ) # List of files simTable = QTreeWidget( self.bodyWidget ) simTable.setAlternatingRowColors( True ) simTable.setRootIsDecorated( False ) simTable.setItemsExpandable( False ) simTable.setSortingEnabled( False ) simTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) simTable.setUniformRowHeights( True ) simTable.itemActivated.connect( self.__similarityActivated ) simTable.setHeaderLabels( [ "File name", "Line" ] ) for item in similarity.files: values = [ item[ 0 ], str( item[ 1 ] ) ] simTable.addTopLevelItem( QTreeWidgetItem( values ) ) # Resizing simTable.header().resizeSections( QHeaderView.ResizeToContents ) simTable.header().setStretchLastSection( True ) # Height self.__setTableHeight( simTable ) self.__vLayout.addWidget( simTable ) self.__widgets.append( simTable ) # The fragment itself if len( similarity.fragment ) > 10: # Take first 9 lines text = "\n".join( similarity.fragment[ : 9 ] ) + "\n ..." toolTip = "\n".join( similarity.fragment ) else: text = "\n".join( similarity.fragment ) toolTip = "" fragmentLabel = QLabel( "<pre>" + self.__htmlEncode( text ) + "</pre>" ) if toolTip != "": fragmentLabel.setToolTip( "<pre>" + self.__htmlEncode( toolTip ) + "</pre>" ) palette = fragmentLabel.palette() palette.setColor( QPalette.Background, QColor( 250, 250, 175 ) ) palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) ) fragmentLabel.setPalette( palette ) fragmentLabel.setFrameShape( QFrame.StyledPanel ) fragmentLabel.setAutoFillBackground( True ) labelFont = fragmentLabel.font() labelFont.setFamily( GlobalData().skin.baseMonoFontFace ) fragmentLabel.setFont( labelFont ) self.__vLayout.addWidget( fragmentLabel ) self.__widgets.append( fragmentLabel ) return
class Main(plugin.Plugin): " Main Class " def initialize(self, *args, **kwargs): " Init Main Class " super(Main, self).initialize(*args, **kwargs) self.scriptPath, self.scriptArgs = "", [] self.profilerPath, self.tempPath = profilerPath, tempPath self.output = " ERROR: FAIL: No output ! " self.process = QProcess() self.process.finished.connect(self.on_process_finished) self.process.error.connect(self.on_process_error) self.tabWidget, self.stat = QTabWidget(), QWidget() self.tabWidget.tabCloseRequested.connect( lambda: self.tabWidget.setTabPosition(1) if self.tabWidget. tabPosition() == 0 else self.tabWidget.setTabPosition(0)) self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}') self.tabWidget.setMovable(True) self.tabWidget.setTabsClosable(True) self.vboxlayout1 = QVBoxLayout(self.stat) self.hboxlayout1 = QHBoxLayout() self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat) self.hboxlayout1.addWidget(self.filterTableLabel) self.filterTableLineEdit = QLineEdit(self.stat) self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ') self.hboxlayout1.addWidget(self.filterTableLineEdit) self.filterHintTableLabel = QLabel(" ? ", self.stat) self.hboxlayout1.addWidget(self.filterHintTableLabel) self.vboxlayout1.addLayout(self.hboxlayout1) self.tableWidget = QTableWidget(self.stat) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setColumnCount(8) self.tableWidget.setRowCount(2) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(1, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(2, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(3, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(4, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(5, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(6, item) item = QTableWidgetItem() self.tableWidget.setHorizontalHeaderItem(7, item) self.tableWidget.itemDoubleClicked.connect( self.on_tableWidget_itemDoubleClicked) self.vboxlayout1.addWidget(self.tableWidget) self.tabWidget.addTab(self.stat, " ? ") self.source = QWidget() self.gridlayout = QGridLayout(self.source) self.scintillaWarningLabel = QLabel( "QScintilla is not installed!. Falling back to basic text edit!.", self.source) self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2) self.sourceTreeWidget = QTreeWidget(self.source) self.sourceTreeWidget.setAlternatingRowColors(True) self.sourceTreeWidget.itemActivated.connect( self.on_sourceTreeWidget_itemActivated) self.sourceTreeWidget.itemClicked.connect( self.on_sourceTreeWidget_itemClicked) self.sourceTreeWidget.itemDoubleClicked.connect( self.on_sourceTreeWidget_itemClicked) self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1) self.sourceTextEdit = QTextEdit(self.source) self.sourceTextEdit.setReadOnly(True) self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1) self.tabWidget.addTab(self.source, " ? ") self.result = QWidget() self.vlayout = QVBoxLayout(self.result) self.globalStatGroupBox = QGroupBox(self.result) self.hboxlayout = QHBoxLayout(self.globalStatGroupBox) self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox) self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.totalTimeLcdNumber.setNumDigits(7) self.totalTimeLcdNumber.display(1000000) self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel) self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.totalTimeLcdNumber) self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>", self.globalStatGroupBox) self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.tTimeLabel) self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.numCallLcdNumber.setNumDigits(7) self.numCallLcdNumber.display(1000000) self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.numCallLcdNumber) self.numCallLabel = QLabel("<b>Number of calls</b>", self.globalStatGroupBox) self.numCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.numCallLabel) self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox) self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled) self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel) self.primCallLcdNumber.setNumDigits(7) self.primCallLcdNumber.display(1000000) self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.hboxlayout.addWidget(self.primCallLcdNumber) self.primCallLabel = QLabel("<b>Primitive calls (%)</b>", self.globalStatGroupBox) self.primCallLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.hboxlayout.addWidget(self.primCallLabel) self.vlayout.addWidget(self.globalStatGroupBox) try: from PyKDE4.kdeui import KRatingWidget self.rating = KRatingWidget(self.globalStatGroupBox) self.rating.setToolTip('Profiling Performance Rating') except ImportError: pass self.tabWidget.addTab(self.result, " Get Results ! ") self.resgraph = QWidget() self.vlayout2 = QVBoxLayout(self.result) self.graphz = QGroupBox(self.resgraph) self.hboxlayout2 = QHBoxLayout(self.graphz) try: from PyKDE4.kdeui import KLed KLed(self.graphz) except ImportError: pass self.hboxlayout2.addWidget( QLabel(''' Work in Progress :) Not Ready Yet''')) self.vlayout2.addWidget(self.graphz) self.tabWidget.addTab(self.resgraph, " Graphs and Charts ") self.pathz = QWidget() self.vlayout3 = QVBoxLayout(self.pathz) self.patz = QGroupBox(self.pathz) self.hboxlayout3 = QVBoxLayout(self.patz) self.profilepath = QLineEdit(profilerPath) self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open') self.getprofile.setToolTip( 'Dont touch if you dont know what are doing') self.getprofile.clicked.connect(lambda: self.profilepath.setText( str( QFileDialog.getOpenFileName( self.patz, ' Open the profile.py file ', path.expanduser("~"), ';;(profile.py)')))) self.hboxlayout3.addWidget( QLabel( '<center><b>Profile.py Python Library Full Path:</b></center>') ) self.hboxlayout3.addWidget(self.profilepath) self.hboxlayout3.addWidget(self.getprofile) self.argGroupBox = QGroupBox(self.pathz) self.hbxlayout = QHBoxLayout(self.argGroupBox) self.argLineEdit = QLineEdit(self.argGroupBox) self.argLineEdit.setToolTip( 'Not touch if you dont know what are doing') self.argLineEdit.setPlaceholderText( 'Dont touch if you dont know what are doing') self.hbxlayout.addWidget( QLabel('<b>Additional Profile Arguments:</b>')) self.hbxlayout.addWidget(self.argLineEdit) self.hboxlayout3.addWidget(self.argGroupBox) self.vlayout3.addWidget(self.patz) self.tabWidget.addTab(self.pathz, " Paths and Configs ") self.outp = QWidget() self.vlayout4 = QVBoxLayout(self.outp) self.outgro = QGroupBox(self.outp) self.outgro.setTitle(" MultiProcessing Output Logs ") self.hboxlayout4 = QVBoxLayout(self.outgro) self.outputlog = QTextEdit() self.outputlog.setText(''' I do not fear computers, I fear the lack of them. -Isaac Asimov ''') self.hboxlayout4.addWidget(self.outputlog) self.vlayout4.addWidget(self.outgro) self.tabWidget.addTab(self.outp, " Logs ") self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"), 'New Profiling', self) self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"), 'Open Profiling', self) self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean', self) self.actionClean.triggered.connect(lambda: self.clearContent) self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About', self) self.actionAbout.triggered.connect(lambda: QMessageBox.about( self.dock, __doc__, ', '.join( (__doc__, __license__, __author__, __email__)))) self.actionSave_profile = QAction(QIcon.fromTheme("document-save"), 'Save Profiling', self) self.actionManual = QAction(QIcon.fromTheme("help-contents"), 'Help', self) self.actionManual.triggered.connect(lambda: open_new_tab( 'http://docs.python.org/library/profile.html')) self.tabWidget.setCurrentIndex(2) self.globalStatGroupBox.setTitle("Global Statistics") item = self.tableWidget.horizontalHeaderItem(0) item.setText("Number of Calls") item = self.tableWidget.horizontalHeaderItem(1) item.setText("Total Time") item = self.tableWidget.horizontalHeaderItem(2) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(3) item.setText("Cumulative Time") item = self.tableWidget.horizontalHeaderItem(4) item.setText("Per Call") item = self.tableWidget.horizontalHeaderItem(5) item.setText("Filename") item = self.tableWidget.horizontalHeaderItem(6) item.setText("Line") item = self.tableWidget.horizontalHeaderItem(7) item.setText("Function") self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat), "Statistics per Function") self.sourceTreeWidget.headerItem().setText(0, "Source files") self.tabWidget.setTabText(self.tabWidget.indexOf(self.source), "Sources Navigator") ####################################################################### self.scrollable, self.dock = QScrollArea(), QDockWidget() self.scrollable.setWidgetResizable(True) self.scrollable.setWidget(self.tabWidget) self.dock.setWindowTitle(__doc__) self.dock.setStyleSheet('QDockWidget::title{text-align: center;}') self.dock.setWidget(self.scrollable) QToolBar(self.dock).addActions( (self.actionNew_profiling, self.actionClean, self.actionSave_profile, self.actionLoad_profile, self.actionManual, self.actionAbout)) self.actionNew_profiling.triggered.connect( self.on_actionNew_profiling_triggered) self.actionLoad_profile.triggered.connect( self.on_actionLoad_profile_triggered) self.actionSave_profile.triggered.connect( self.on_actionSave_profile_triggered) self.locator.get_service('misc').add_widget( self.dock, QIcon.fromTheme("document-open-recent"), __doc__) if QSCI: # Scintilla source editor management self.scintillaWarningLabel.setText(' QScintilla is Ready ! ') layout = self.source.layout() layout.removeWidget(self.sourceTextEdit) self.sourceTextEdit = Qsci.QsciScintilla(self.source) layout.addWidget(self.sourceTextEdit, 0, 1) doc = self.sourceTextEdit doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit)) doc.setReadOnly(True) doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine) doc.setEdgeColumn(80) doc.setEdgeColor(QColor("#FF0000")) doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle) doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch) doc.setCaretLineVisible(True) doc.setMarginLineNumbers(1, True) doc.setMarginWidth(1, 25) doc.setTabWidth(4) doc.setEolMode(Qsci.QsciScintilla.EolUnix) self.marker = {} for color in COLORS: mnr = doc.markerDefine(Qsci.QsciScintilla.Background) doc.setMarkerBackgroundColor(color, mnr) self.marker[color] = mnr self.currentSourcePath = None # Connect table and tree filter edit signal to unique slot self.filterTableLineEdit.textEdited.connect( self.on_filterLineEdit_textEdited) # Timer to display filter hint message self.filterHintTimer = QTimer(self) self.filterHintTimer.setSingleShot(True) self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout) # Timer to start search self.filterSearchTimer = QTimer(self) self.filterSearchTimer.setSingleShot(True) self.filterSearchTimer.timeout.connect( self.on_filterSearchTimer_timeout) self.tabLoaded = {} for i in range(10): self.tabLoaded[i] = False self.backgroundTreeMatchedItems = {} self.resizeWidgetToContent(self.tableWidget) def on_actionNew_profiling_triggered(self): self.clearContent() self.scriptPath = str( QFileDialog.getOpenFileName(self.dock, "Choose your script to profile", path.expanduser("~"), "Python (*.py *.pyw)")) commandLine = [ self.profilerPath, "-o", self.tempPath, self.scriptPath ] + self.scriptArgs commandLine = " ".join(commandLine) ##if self.termCheckBox.checkState() == Qt.Checked: #termList = ["xterm", "aterm"] #for term in termList: #termPath = which(term) #if termPath: #break #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \ #% (termPath, commandLine) self.process.start(commandLine) if not self.process.waitForStarted(): print((" ERROR: {} failed!".format(commandLine))) return def on_process_finished(self, exitStatus): ' whan the process end ' print((" INFO: OK: QProcess is %s" % self.process.exitCode())) self.output = self.process.readAll().data() if not self.output: self.output = " ERROR: FAIL: No output ! " self.outputlog.setText(self.output + str(self.process.exitCode())) if path.exists(self.tempPath): self.setStat(self.tempPath) remove(self.tempPath) else: self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.") self.tabWidget.setCurrentIndex(2) def on_process_error(self, error): ' when the process fail, I hope you never see this ' print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ") if error == QProcess.FailedToStart: self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ") elif error == QProcess.Crashed: self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ") else: self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ") def on_actionLoad_profile_triggered(self): """Load a previous profile sessions""" statPath = str( QFileDialog.getOpenFileName(self.dock, "Open profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: self.clearContent() print(' INFO: OK: Loading profiling from ' + statPath) self.setStat(statPath) def on_actionSave_profile_triggered(self): """Save a profile sessions""" statPath = str( QFileDialog.getSaveFileName(self.dock, "Save profile dump", path.expanduser("~"), "Profile file (*)")) if statPath: #TODO: handle error case and give feelback to user print(' INFO: OK: Saving profiling to ' + statPath) self.stat.save(statPath) #=======================================================================# # Common parts # #=======================================================================# def on_tabWidget_currentChanged(self, index): """slot for tab change""" # Kill search and hint timer if running to avoid cross effect for timer in (self.filterHintTimer, self.filterSearchTimer): if timer.isActive(): timer.stop() if not self.stat: #No stat loaded, nothing to do return self.populateTable() self.populateSource() def on_filterLineEdit_textEdited(self, text): """slot for filter change (table or tree""" if self.filterSearchTimer.isActive(): # Already runnning, stop it self.filterSearchTimer.stop() # Start timer self.filterSearchTimer.start(300) def on_filterHintTimer_timeout(self): """Timeout to warn user about text length""" print("timeout") tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: label = self.filterHintTableLabel label.setText("Type > 2 characters to search") def on_filterSearchTimer_timeout(self): """timeout to start search""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: text = self.filterTableLineEdit.text() label = self.filterHintTableLabel edit = self.filterTableLineEdit widget = self.tableWidget else: print("Unknow tab for filterSearch timeout !") print(("do search for %s" % text)) if not len(text): # Empty keyword, just clean all if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") self.warnUSer(True, edit) self.clearSearch() return if len(text) < 2: # Don't filter if text is too short and tell it to user self.filterHintTimer.start(600) return else: if self.filterHintTimer.isActive(): self.filterHintTimer.stop() label.setText(" ? ") # Search self.clearSearch() matchedItems = [] if tab == TAB_FUNCTIONSTAT: # Find items matchedItems = widget.findItems(text, Qt.MatchContains) widget.setSortingEnabled(False) matchedRows = [item.row() for item in matchedItems] # Hide matched items header = widget.verticalHeader() for row in range(widget.rowCount()): if row not in matchedRows: header.hideSection(row) widget.setSortingEnabled(True) else: print(" Unknow tab for filterSearch timeout ! ") print(("got %s members" % len(matchedItems))) self.warnUSer(matchedItems, edit) self.resizeWidgetToContent(widget) def resizeWidgetToContent(self, widget): """Resize all columns according to content""" for i in range(widget.columnCount()): widget.resizeColumnToContents(i) def clearSearch(self): """Clean search result For table, show all items For tree, remove colored items""" tab = self.tabWidget.currentIndex() if tab == TAB_FUNCTIONSTAT: header = self.tableWidget.verticalHeader() if header.hiddenSectionCount(): for i in range(header.count()): if header.isSectionHidden(i): header.showSection(i) def clearContent(self): # Clear tabs self.tableWidget.clearContents() self.sourceTreeWidget.clear() # Reset LCD numbers for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber, self.primCallLcdNumber): lcdNumber.display(1000000) # Reset stat self.pstat = None # Disable save as menu self.actionSave_profile.setEnabled(False) # Mark all tabs as unloaded for i in range(10): self.tabLoaded[i] = False def warnUSer(self, result, inputWidget): palette = inputWidget.palette() if result: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 255, 255)) else: palette.setColor(QPalette.Normal, QPalette.Base, QColor(255, 136, 138)) inputWidget.setPalette(palette) inputWidget.update() def setStat(self, statPath): self.stat = Stat(path=statPath) # Global stat update self.totalTimeLcdNumber.display(self.stat.getTotalTime()) self.numCallLcdNumber.display(self.stat.getCallNumber()) self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio()) # Refresh current tab self.on_tabWidget_currentChanged(self.tabWidget.currentIndex()) # Activate save as menu self.actionSave_profile.setEnabled(True) try: self.rating.setMaxRating(10) self.rating.setRating( int(self.stat.getPrimitiveCallRatio()) / 10 - 1) except: pass #========================================================================# # Statistics table # #=======================================================================# def populateTable(self): row = 0 rowCount = self.stat.getStatNumber() progress = QProgressDialog("Populating statistics table...", "Abort", 0, 2 * rowCount) self.tableWidget.setSortingEnabled(False) self.tableWidget.setRowCount(rowCount) progress.setWindowModality(Qt.WindowModal) for (key, value) in self.stat.getStatItems(): #ncalls item = StatTableWidgetItem(str(value[0])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_NCALLS, item) colorTableItem(item, self.stat.getCallNumber(), value[0]) #total time item = StatTableWidgetItem(str(value[2])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[2]) #per call (total time) if value[0] != 0: tPerCall = str(value[2] / value[0]) cPerCall = str(value[3] / value[0]) else: tPerCall = "" cPerCall = "" item = StatTableWidgetItem(tPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_TPERCALL, item) colorTableItem( item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), tPerCall) #per call (cumulative time) item = StatTableWidgetItem(cPerCall) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CPERCALL, item) colorTableItem( item, 100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(), cPerCall) #cumulative time item = StatTableWidgetItem(str(value[3])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_CTIME, item) colorTableItem(item, self.stat.getTotalTime(), value[3]) #Filename self.tableWidget.setItem(row, STAT_FILENAME, StatTableWidgetItem(str(key[0]))) #Line item = StatTableWidgetItem(str(key[1])) item.setTextAlignment(Qt.AlignRight) self.tableWidget.setItem(row, STAT_LINE, item) #Function name self.tableWidget.setItem(row, STAT_FUNCTION, StatTableWidgetItem(str(key[2]))) row += 1 # Store it in stat hash array self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT) progress.setValue(row) if progress.wasCanceled(): return for i in range(self.tableWidget.rowCount()): progress.setValue(row + i) for j in range(self.tableWidget.columnCount()): item = self.tableWidget.item(i, j) if item: item.setFlags(Qt.ItemIsEnabled) self.tableWidget.setSortingEnabled(True) self.resizeWidgetToContent(self.tableWidget) progress.setValue(2 * rowCount) def on_tableWidget_itemDoubleClicked(self, item): matchedItems = [] filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text()) if not filename or filename.startswith("<"): # No source code associated, return immediatly return function = self.tableWidget.item(item.row(), STAT_FUNCTION).text() line = self.tableWidget.item(item.row(), STAT_LINE).text() self.on_tabWidget_currentChanged(TAB_SOURCE) # load source tab function = "%s (%s)" % (function, line) fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains, SOURCE_FILENAME) print(("find %s father" % len(fathers))) for father in fathers: findItems(father, function, SOURCE_FILENAME, matchedItems) print(("find %s items" % len(matchedItems))) if matchedItems: self.tabWidget.setCurrentIndex(TAB_SOURCE) self.sourceTreeWidget.scrollToItem(matchedItems[0]) self.on_sourceTreeWidget_itemClicked(matchedItems[0], SOURCE_FILENAME) matchedItems[0].setSelected(True) else: print("oups, item found but cannot scroll to it !") #=======================================================================# # Source explorer # #=====================================================================# def populateSource(self): items = {} for stat in self.stat.getStatKeys(): source = stat[0] function = "%s (%s)" % (stat[2], stat[1]) if source in ("", "profile") or source.startswith("<"): continue # Create the function child child = QTreeWidgetItem([function]) # Store it in stat hash array self.stat.setStatLink(child, stat, TAB_SOURCE) if source in items: father = items[source] else: # Create the father father = QTreeWidgetItem([source]) items[source] = father father.addChild(child) self.sourceTreeWidget.setSortingEnabled(False) for value in list(items.values()): self.sourceTreeWidget.addTopLevelItem(value) self.sourceTreeWidget.setSortingEnabled(True) def on_sourceTreeWidget_itemActivated(self, item, column): self.on_sourceTreeWidget_itemClicked(item, column) def on_sourceTreeWidget_itemClicked(self, item, column): line = 0 parent = item.parent() if QSCI: doc = self.sourceTextEdit if parent: pathz = parent.text(column) result = match("(.*) \(([0-9]+)\)", item.text(column)) if result: try: function = str(result.group(1)) line = int(result.group(2)) except ValueError: # We got garbage... falling back to line 0 pass else: pathz = item.text(column) pathz = path.abspath(str(pathz)) if self.currentSourcePath != pathz: # Need to load source self.currentSourcePath == pathz try: if QSCI: doc.clear() doc.insert(file(pathz).read()) else: self.sourceTextEdit.setPlainText(file(pathz).read()) except IOError: QMessageBox.warning(self, "Error", "Source file could not be found", QMessageBox.Ok) return if QSCI: for function, line in [(i[2], i[1]) for i in self.stat.getStatKeys() if i[0] == pathz]: # expr, regexp, case sensitive, whole word, wrap, forward doc.findFirst("def", False, True, True, False, True, line, 0, True) end, foo = doc.getCursorPosition() time = self.stat.getStatTotalTime((pathz, line, function)) colorSource(doc, self.stat.getTotalTime(), time, line, end, self.marker) if QSCI: doc.ensureLineVisible(line)
class EditorConfiguration(QWidget): """EditorConfiguration widget class""" def __init__(self, parent): super(EditorConfiguration, self).__init__() self._preferences, vbox = parent, QVBoxLayout(self) # groups group1 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_INDENT) group2 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_MARGIN) group3 = QGroupBox(translations.TR_LINT_DIRTY_TEXT) group4 = QGroupBox(translations.TR_PEP8_DIRTY_TEXT) group5 = QGroupBox(translations.TR_HIGHLIGHTER_EXTRAS) group6 = QGroupBox(translations.TR_TYPING_ASSISTANCE) group7 = QGroupBox(translations.TR_DISPLAY) # groups container container_widget_with_all_preferences = QWidget() formFeatures = QGridLayout(container_widget_with_all_preferences) # Indentation hboxg1 = QHBoxLayout(group1) hboxg1.setContentsMargins(5, 15, 5, 5) self._spin, self._checkUseTabs = QSpinBox(), QComboBox() self._spin.setRange(1, 10) self._spin.setValue(settings.INDENT) hboxg1.addWidget(self._spin) self._checkUseTabs.addItems([ translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES.capitalize(), translations.TR_PREFERENCES_EDITOR_CONFIG_TABS.capitalize() ]) self._checkUseTabs.setCurrentIndex(int(settings.USE_TABS)) hboxg1.addWidget(self._checkUseTabs) formFeatures.addWidget(group1, 0, 0) # Margin Line hboxg2 = QHBoxLayout(group2) hboxg2.setContentsMargins(5, 15, 5, 5) self._checkShowMargin = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MARGIN_LINE) self._checkShowMargin.setChecked(settings.SHOW_MARGIN_LINE) hboxg2.addWidget(self._checkShowMargin) self._spinMargin = QSpinBox() self._spinMargin.setRange(50, 100) self._spinMargin.setSingleStep(2) self._spinMargin.setValue(settings.MARGIN_LINE) hboxg2.addWidget(self._spinMargin) hboxg2.addWidget(QLabel(translations.TR_CHARACTERS)) formFeatures.addWidget(group2, 0, 1) # Display Errors vboxDisplay = QVBoxLayout(group7) vboxDisplay.setContentsMargins(5, 15, 5, 5) self._checkHighlightLine = QComboBox() self._checkHighlightLine.addItems([ translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_BACKGROUND, translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_UNDERLINE ]) self._checkHighlightLine.setCurrentIndex( int(settings.UNDERLINE_NOT_BACKGROUND)) hboxDisplay1 = QHBoxLayout() hboxDisplay1.addWidget(QLabel(translations.TR_DISPLAY_ERRORS)) hboxDisplay1.addWidget(self._checkHighlightLine) hboxDisplay2 = QHBoxLayout() self._checkDisplayLineNumbers = QCheckBox( translations.TR_DISPLAY_LINE_NUMBERS) self._checkDisplayLineNumbers.setChecked(settings.SHOW_LINE_NUMBERS) hboxDisplay2.addWidget(self._checkDisplayLineNumbers) vboxDisplay.addLayout(hboxDisplay1) vboxDisplay.addLayout(hboxDisplay2) formFeatures.addWidget(group7, 1, 0, 1, 0) # Find Lint Errors (highlighter) vboxg3 = QVBoxLayout(group3) self._checkErrors = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_FIND_ERRORS) self._checkErrors.setChecked(settings.FIND_ERRORS) self.connect(self._checkErrors, SIGNAL("stateChanged(int)"), self._disable_show_errors) self._showErrorsOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_ERRORS) self._showErrorsOnLine.setChecked(settings.ERRORS_HIGHLIGHT_LINE) self.connect(self._showErrorsOnLine, SIGNAL("stateChanged(int)"), self._enable_errors_inline) vboxg3.addWidget(self._checkErrors) vboxg3.addWidget(self._showErrorsOnLine) vboxg3.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) formFeatures.addWidget(group3, 2, 0) # Find PEP8 Errors (highlighter) vboxg4 = QHBoxLayout(group4) vboxg4.setContentsMargins(5, 15, 5, 5) vvbox = QVBoxLayout() self._checkStyle = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_PEP8) self._checkStyle.setChecked(settings.CHECK_STYLE) self.connect(self._checkStyle, SIGNAL("stateChanged(int)"), self._disable_check_style) vvbox.addWidget(self._checkStyle) self._checkStyleOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_PEP8) self._checkStyleOnLine.setChecked(settings.CHECK_HIGHLIGHT_LINE) self.connect(self._checkStyleOnLine, SIGNAL("stateChanged(int)"), self._enable_check_inline) vvbox.addWidget(self._checkStyleOnLine) vvbox.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) vboxg4.addLayout(vvbox) # Container for tree widget and buttons widget = QWidget() hhbox = QHBoxLayout(widget) hhbox.setContentsMargins(0, 0, 0, 0) # Tree Widget with custom item delegate # always adds uppercase text self._listIgnoreViolations = QTreeWidget() self._listIgnoreViolations.setObjectName("ignore_pep8") self._listIgnoreViolations.setItemDelegate(ui_tools.CustomDelegate()) self._listIgnoreViolations.setMaximumHeight(80) self._listIgnoreViolations.setHeaderLabel( translations.TR_PREFERENCES_EDITOR_CONFIG_IGNORE_PEP8) for ic in settings.IGNORE_PEP8_LIST: self._listIgnoreViolations.addTopLevelItem(QTreeWidgetItem([ic])) hhbox.addWidget(self._listIgnoreViolations) box = QVBoxLayout() box.setContentsMargins(0, 0, 0, 0) btn_add = QPushButton(QIcon(":img/add_small"), '') btn_add.setMaximumSize(26, 24) btn_add.clicked.connect(self._add_code_pep8) box.addWidget(btn_add) btn_remove = QPushButton(QIcon(":img/delete_small"), '') btn_remove.setMaximumSize(26, 24) btn_remove.clicked.connect(self._remove_code_pep8) box.addWidget(btn_remove) box.addItem(QSpacerItem(0, 0, QSizePolicy.Fixed, QSizePolicy.Expanding)) hhbox.addLayout(box) vboxg4.addWidget(widget) formFeatures.addWidget(group4) # Show Python3 Migration, DocStrings and Spaces (highlighter) vboxg5 = QVBoxLayout(group5) vboxg5.setContentsMargins(5, 15, 5, 5) self._showMigrationTips = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MIGRATION) self._showMigrationTips.setChecked(settings.SHOW_MIGRATION_TIPS) vboxg5.addWidget(self._showMigrationTips) self._checkForDocstrings = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_CHECK_FOR_DOCSTRINGS) self._checkForDocstrings.setChecked(settings.CHECK_FOR_DOCSTRINGS) vboxg5.addWidget(self._checkForDocstrings) self._checkShowSpaces = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TABS_AND_SPACES) self._checkShowSpaces.setChecked(settings.SHOW_TABS_AND_SPACES) vboxg5.addWidget(self._checkShowSpaces) self._checkIndentationGuide = QCheckBox( translations.TR_SHOW_INDENTATION_GUIDE) self._checkIndentationGuide.setChecked(settings.SHOW_INDENTATION_GUIDE) vboxg5.addWidget(self._checkIndentationGuide) formFeatures.addWidget(group5, 3, 0) # End of line, Stop Scrolling At Last Line, Trailing space, Word wrap vboxg6 = QVBoxLayout(group6) vboxg6.setContentsMargins(5, 15, 5, 5) self._checkEndOfLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_END_OF_LINE) self._checkEndOfLine.setChecked(settings.USE_PLATFORM_END_OF_LINE) vboxg6.addWidget(self._checkEndOfLine) self._checkEndAtLastLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_END_AT_LAST_LINE) self._checkEndAtLastLine.setChecked(settings.END_AT_LAST_LINE) vboxg6.addWidget(self._checkEndAtLastLine) self._checkTrailing = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_REMOVE_TRAILING) self._checkTrailing.setChecked(settings.REMOVE_TRAILING_SPACES) vboxg6.addWidget(self._checkTrailing) self._allowWordWrap = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_WORD_WRAP) self._allowWordWrap.setChecked(settings.ALLOW_WORD_WRAP) vboxg6.addWidget(self._allowWordWrap) formFeatures.addWidget(group6, 3, 1) # pack all the groups vbox.addWidget(container_widget_with_all_preferences) vbox.addItem( QSpacerItem(0, 10, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.connect(self._preferences, SIGNAL("savePreferences()"), self.save) def _add_code_pep8(self): item = QTreeWidgetItem() item.setFlags(item.flags() | Qt.ItemIsEditable) self._listIgnoreViolations.addTopLevelItem(item) self._listIgnoreViolations.setCurrentItem(item) self._listIgnoreViolations.editItem(item, 0) def _remove_code_pep8(self): index = self._listIgnoreViolations.indexOfTopLevelItem( self._listIgnoreViolations.currentItem()) self._listIgnoreViolations.takeTopLevelItem(index) def _enable_check_inline(self, val): """Method that takes a value to enable the inline style checking""" if val == Qt.Checked: self._checkStyle.setChecked(True) def _enable_errors_inline(self, val): """Method that takes a value to enable the inline errors checking""" if val == Qt.Checked: self._checkErrors.setChecked(True) def _disable_check_style(self, val): """Method that takes a value to disable the inline style checking""" if val == Qt.Unchecked: self._checkStyleOnLine.setChecked(False) def _disable_show_errors(self, val): """Method that takes a value to disable the inline errors checking""" if val == Qt.Unchecked: self._showErrorsOnLine.setChecked(False) def save(self): """Method to save settings""" qsettings = IDE.ninja_settings() settings.USE_TABS = bool(self._checkUseTabs.currentIndex()) qsettings.setValue('preferences/editor/useTabs', settings.USE_TABS) margin_line = self._spinMargin.value() settings.MARGIN_LINE = margin_line settings.pycodestylemod_update_margin_line_length(margin_line) qsettings.setValue('preferences/editor/marginLine', margin_line) settings.SHOW_MARGIN_LINE = self._checkShowMargin.isChecked() qsettings.setValue('preferences/editor/showMarginLine', settings.SHOW_MARGIN_LINE) settings.INDENT = self._spin.value() qsettings.setValue('preferences/editor/indent', settings.INDENT) endOfLine = self._checkEndOfLine.isChecked() settings.USE_PLATFORM_END_OF_LINE = endOfLine qsettings.setValue('preferences/editor/platformEndOfLine', endOfLine) settings.UNDERLINE_NOT_BACKGROUND = \ bool(self._checkHighlightLine.currentIndex()) qsettings.setValue('preferences/editor/errorsUnderlineBackground', settings.UNDERLINE_NOT_BACKGROUND) settings.FIND_ERRORS = self._checkErrors.isChecked() qsettings.setValue('preferences/editor/errors', settings.FIND_ERRORS) settings.ERRORS_HIGHLIGHT_LINE = self._showErrorsOnLine.isChecked() qsettings.setValue('preferences/editor/errorsInLine', settings.ERRORS_HIGHLIGHT_LINE) settings.CHECK_STYLE = self._checkStyle.isChecked() qsettings.setValue('preferences/editor/checkStyle', settings.CHECK_STYLE) settings.SHOW_MIGRATION_TIPS = self._showMigrationTips.isChecked() qsettings.setValue('preferences/editor/showMigrationTips', settings.SHOW_MIGRATION_TIPS) settings.CHECK_HIGHLIGHT_LINE = self._checkStyleOnLine.isChecked() qsettings.setValue('preferences/editor/checkStyleInline', settings.CHECK_HIGHLIGHT_LINE) settings.END_AT_LAST_LINE = self._checkEndAtLastLine.isChecked() qsettings.setValue('preferences/editor/endAtLastLine', settings.END_AT_LAST_LINE) settings.REMOVE_TRAILING_SPACES = self._checkTrailing.isChecked() qsettings.setValue('preferences/editor/removeTrailingSpaces', settings.REMOVE_TRAILING_SPACES) settings.ALLOW_WORD_WRAP = self._allowWordWrap.isChecked() qsettings.setValue('preferences/editor/allowWordWrap', settings.ALLOW_WORD_WRAP) settings.SHOW_TABS_AND_SPACES = self._checkShowSpaces.isChecked() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) settings.SHOW_INDENTATION_GUIDE = ( self._checkIndentationGuide.isChecked()) qsettings.setValue('preferences/editor/showIndentationGuide', settings.SHOW_INDENTATION_GUIDE) settings.CHECK_FOR_DOCSTRINGS = self._checkForDocstrings.isChecked() qsettings.setValue('preferences/editor/checkForDocstrings', settings.CHECK_FOR_DOCSTRINGS) settings.SHOW_LINE_NUMBERS = self._checkDisplayLineNumbers.isChecked() qsettings.setValue('preferences/editor/showLineNumbers', settings.SHOW_LINE_NUMBERS) current_ignores = set(settings.IGNORE_PEP8_LIST) new_ignore_codes = [] # Get pep8 from tree widget for index in range(self._listIgnoreViolations.topLevelItemCount()): ignore_code = self._listIgnoreViolations.topLevelItem(index).text( 0) if ignore_code: new_ignore_codes.append(ignore_code.strip()) # pep8 list that will be removed to_remove = [x for x in current_ignores if x not in new_ignore_codes] # Update list settings.IGNORE_PEP8_LIST = new_ignore_codes qsettings.setValue('preferences/editor/defaultIgnorePep8', settings.IGNORE_PEP8_LIST) # Add for ignore_code in settings.IGNORE_PEP8_LIST: settings.pycodestylemod_add_ignore(ignore_code) # Remove for ignore_code in to_remove: settings.pycodestylemod_remove_ignore(ignore_code) if settings.USE_TABS: settings.pycodestylemod_add_ignore("W191") else: settings.pycodestylemod_remove_ignore("W191")
class DBBrowser(QMainWindow): def __init__(self, parent, server): QMainWindow.__init__(self, parent) self.debug = False self.server = server self.db = None self.setWindowTitle("Database Browser") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) topBar = QToolBar() self.addToolBar(Qt.TopToolBarArea, topBar) self.cenWid = QWidget() self.setCentralWidget(self.cenWid) self.mainLayout = QHBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.cenWid.setLayout(self.mainLayout) self.treeTables = QTreeWidget() self.mainLayout.addWidget(self.treeTables, 1) self.treeTables.setHeaderLabels(["Table"]) self.treeTables.setSelectionBehavior(QAbstractItemView.SelectRows) self.treeTables.setSelectionMode(QTreeView.SingleSelection) self.connect(self.treeTables, SIGNAL('itemSelectionChanged()'), self.on_table) self.treeColumns = QTreeWidget() self.mainLayout.addWidget(self.treeColumns, 4) self.treeColumns.setHeaderLabels(["Column", "Type", "Nullable"]) self.db_connect() #self.fetch() def on_table(self): item = self.treeTables.currentItem() if item == None: return self.fetch(table=str(item.text(0))) def db_connect(self): #print "db_connect", self.server self.db = QSqlDatabase.addDatabase("QMYSQL") self.db.setHostName(self.server['server']) self.db.setUserName(self.server['user']) self.db.setPassword(self.server['passwd']) ok = self.db.open() print "open", ok #self.db.setHostName(self.server['server']) def load_data(self, data): if "tables" in data: self.treeTables.clear() for t in data['tables']: item = QTreeWidgetItem() item.setText(0, t['table']) self.treeTables.addTopLevelItem(item) else: self.treeColumns.clear() for t in data['columns']: item = QTreeWidgetItem() item.setText(0, t['column']) item.setText(1, t['type']) item.setText(2, "Yes" if t['nullable'] else "-") self.treeColumns.addTopLevelItem(item)
class ChangedDocumentsListDialog(widgets.dialog.Dialog): def __init__(self): super(ChangedDocumentsListDialog, self).__init__(buttons=('close', )) self.setWindowModality(Qt.NonModal) self.setAttribute(Qt.WA_QuitOnClose, False) layout = QGridLayout(margin=0) self.mainWidget().setLayout(layout) self.tree = QTreeWidget(headerHidden=True, rootIsDecorated=False, columnCount=2, itemsExpandable=False) self.tree.setSelectionMode(QTreeWidget.ExtendedSelection) self.buttonReload = QPushButton() self.buttonReloadAll = QPushButton() self.buttonSave = QPushButton() self.buttonSaveAll = QPushButton() self.buttonShowDiff = QPushButton() self.checkWatchingEnabled = QCheckBox(checked=enabled()) layout.addWidget(self.tree, 0, 0, 6, 1) layout.addWidget(self.buttonReload, 0, 1) layout.addWidget(self.buttonReloadAll, 1, 1) layout.addWidget(self.buttonSave, 2, 1) layout.addWidget(self.buttonSaveAll, 3, 1) layout.addWidget(self.buttonShowDiff, 4, 1) layout.addWidget(self.checkWatchingEnabled, 6, 0, 1, 2) layout.setRowStretch(5, 10) app.documentClosed.connect(self.removeDocument) app.documentSaved.connect(self.removeDocument) app.documentUrlChanged.connect(self.removeDocument) app.documentLoaded.connect(self.removeDocument) self.tree.itemSelectionChanged.connect(self.updateButtons) self.buttonReload.clicked.connect(self.slotButtonReload) self.buttonReloadAll.clicked.connect(self.slotButtonReloadAll) self.buttonSave.clicked.connect(self.slotButtonSave) self.buttonSaveAll.clicked.connect(self.slotButtonSaveAll) self.buttonShowDiff.clicked.connect(self.slotButtonShowDiff) self.checkWatchingEnabled.toggled.connect(setEnabled) app.translateUI(self) qutil.saveDialogSize(self, 'externalchanges/dialog/size', QSize(400, 200)) userguide.addButton(self.buttonBox(), "externalchanges") self.button('close').setFocus() def translateUI(self): self.setWindowTitle(app.caption(_("Modified Files"))) self.setMessage( _("The following files were modified or deleted by other " "applications:")) self.buttonReload.setText(_("Reload")) self.buttonReload.setToolTip( _("Reloads the selected documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonReloadAll.setText(_("Reload All")) self.buttonReloadAll.setToolTip( _("Reloads all externally modified documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonSave.setText(_("Save")) self.buttonSave.setToolTip( _("Saves the selected documents to disk, overwriting the " "modifications by another program.")) self.buttonSaveAll.setText(_("Save All")) self.buttonSaveAll.setToolTip( _("Saves all documents to disk, overwriting the modifications by " "another program.")) self.buttonShowDiff.setText(_("Show Difference...")) self.buttonShowDiff.setToolTip( _("Shows the differences between the current document " "and the file on disk.")) self.checkWatchingEnabled.setText( _("Enable watching documents for external changes")) self.checkWatchingEnabled.setToolTip( _("If checked, Frescobaldi will warn you when opened files are " "modified or deleted by other applications.")) def setDocuments(self, documents): """Display the specified documents in the list.""" # clear the treewidget for d in self.tree.invisibleRootItem().takeChildren(): for i in d.takeChildren(): i.doc = None # group the documents by directory dirs = {} for d in documents: path = d.url().toLocalFile() if path: dirname, filename = os.path.split(path) dirs.setdefault(dirname, []).append((filename, d)) for dirname in sorted(dirs, key=util.naturalsort): diritem = QTreeWidgetItem() diritem.setText(0, util.homify(dirname)) self.tree.addTopLevelItem(diritem) diritem.setExpanded(True) diritem.setFlags(Qt.ItemIsEnabled) diritem.setIcon(0, icons.get('folder-open')) for filename, document in sorted( dirs[dirname], key=lambda item: util.naturalsort(item[0])): fileitem = QTreeWidgetItem() diritem.addChild(fileitem) if documentwatcher.DocumentWatcher.instance( document).isdeleted(): itemtext = _("[deleted]") icon = "dialog-error" else: itemtext = _("[modified]") icon = "document-edit" fileitem.setIcon(0, icons.get(icon)) fileitem.setText(0, filename) fileitem.setText(1, itemtext) fileitem.doc = document # select the item if there is only one if len(dirs) == 1 and len(list(dirs.values())[0]) == 1: fileitem.setSelected(True) self.tree.resizeColumnToContents(0) self.tree.resizeColumnToContents(1) self.updateButtons() def removeDocument(self, document): """Remove the specified document from our list.""" for d in range(self.tree.topLevelItemCount()): diritem = self.tree.topLevelItem(d) for f in range(diritem.childCount()): if diritem.child(f).doc is document: i = diritem.takeChild(f) i.doc = None if diritem.childCount() == 0: self.tree.takeTopLevelItem(d) break else: continue break self.updateButtons() # hide if no documents are left if self.tree.topLevelItemCount() == 0: self.hide() def selectedDocuments(self): """Return the selected documents.""" return [i.doc for i in self.tree.selectedItems()] def allDocuments(self): """Return all shown documents.""" return [ self.tree.topLevelItem(d).child(f).doc for d in range(self.tree.topLevelItemCount()) for f in range(self.tree.topLevelItem(d).childCount()) ] def updateButtons(self): """Updates the buttons regarding the selection.""" docs_sel = self.selectedDocuments() docs_all = self.allDocuments() all_deleted_sel = all( documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_sel) all_deleted_all = all( documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_all) self.buttonSave.setEnabled(len(docs_sel) > 0) self.buttonSaveAll.setEnabled(len(docs_all) > 0) self.buttonReload.setEnabled(not all_deleted_sel) self.buttonReloadAll.setEnabled(not all_deleted_all) self.buttonShowDiff.setEnabled( len(docs_sel) == 1 and not all_deleted_sel) def slotButtonReload(self): """Called when the user clicks Reload.""" self.reloadDocuments(self.selectedDocuments()) def slotButtonReloadAll(self): """Called when the user clicks Reload All.""" self.reloadDocuments(self.allDocuments()) def slotButtonSave(self): """Called when the user clicks Save.""" self.saveDocuments(self.selectedDocuments()) def slotButtonSaveAll(self): """Called when the user clicks Save All.""" self.saveDocuments(self.allDocuments()) def reloadDocuments(self, documents): """Used by slotButtonReload and slotButtonReloadAll.""" failures = [] for d in documents: try: d.load(keepUndo=True) except IOError as e: failures.append((d, e)) if failures: msg = _("Could not reload:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format(url=d.url().toLocalFile(), strerror=e.strerror, errno=e.errno) for d, e in failures) QMessageBox.critical(self, app.caption(_("Error")), msg) def saveDocuments(self, documents): """Used by slotButtonSave and slotButtonSaveAll.""" failures = [] for d in documents: try: d.save() except IOError as e: failures.append((d, e)) if failures: msg = _("Could not save:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format( url = d.url().toLocalFile(), strerror = e.strerror, errno = e.errno) for d, e in failures) + "\n\n" + \ _("Please save the document using the \"Save As...\" dialog.", "Please save the documents using the \"Save As...\" dialog.", len(failures)) QMessageBox.critical(self, app.caption(_("Error")), msg) def slotButtonShowDiff(self): """Called when the user clicks Show Difference.""" docs = self.selectedDocuments() or self.allDocuments() if not docs: return d = docs[0] if documentwatcher.DocumentWatcher.instance(d).isdeleted(): return filename = d.url().toLocalFile() try: with open(filename, 'rb') as f: disktext = util.decode(f.read()) except (IOError, OSError): return currenttext = d.toPlainText() html = htmldiff.htmldiff(currenttext, disktext, _("Current Document"), _("Document on Disk"), numlines=5) dlg = widgets.dialog.Dialog(self, buttons=('close', )) view = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap) view.setHtml(html) dlg.setMainWidget(view) dlg.setWindowTitle(app.caption("Differences")) dlg.setMessage( _("Document: {url}\n" "Difference between the current document and the file on disk:"). format(url=filename)) dlg.setWindowModality(Qt.NonModal) dlg.setAttribute(Qt.WA_QuitOnClose, False) dlg.setAttribute(Qt.WA_DeleteOnClose) qutil.saveDialogSize(dlg, "externalchanges/diff/dialog/size", QSize(600, 300)) dlg.show()
class DBBrowser(QMainWindow): def __init__(self, parent, server): QMainWindow.__init__(self, parent) self.debug = False self.server = server self.db = None self.setWindowTitle("Database Browser") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) topBar = QToolBar() self.addToolBar(Qt.TopToolBarArea, topBar) self.cenWid = QWidget() self.setCentralWidget(self.cenWid) self.mainLayout = QHBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.cenWid.setLayout( self.mainLayout ) self.treeTables = QTreeWidget() self.mainLayout.addWidget(self.treeTables, 1) self.treeTables.setHeaderLabels(["Table"]) self.treeTables.setSelectionBehavior( QAbstractItemView.SelectRows ) self.treeTables.setSelectionMode( QTreeView.SingleSelection ) self.connect( self.treeTables, SIGNAL( 'itemSelectionChanged()' ), self.on_table ) self.treeColumns = QTreeWidget() self.mainLayout.addWidget(self.treeColumns, 4) self.treeColumns.setHeaderLabels(["Column", "Type", "Nullable"]) self.db_connect() #self.fetch() def on_table(self): item = self.treeTables.currentItem() if item == None: return self.fetch( table = str(item.text(0)) ) def db_connect(self): #print "db_connect", self.server self.db = QSqlDatabase.addDatabase("QMYSQL") self.db.setHostName(self.server['server']) self.db.setUserName(self.server['user']) self.db.setPassword(self.server['passwd']) ok = self.db.open() print "open", ok #self.db.setHostName(self.server['server']) def load_data(self, data): if "tables" in data: self.treeTables.clear() for t in data['tables']: item = QTreeWidgetItem() item.setText(0, t['table']) self.treeTables.addTopLevelItem(item) else: self.treeColumns.clear() for t in data['columns']: item = QTreeWidgetItem() item.setText(0, t['column']) item.setText(1, t['type']) item.setText(2, "Yes" if t['nullable'] else "-") self.treeColumns.addTopLevelItem(item)
class GmApp(QMainWindow): def __init__(self): super(QMainWindow, self).__init__() self.setWindowTitle("GuloMail by GulonSoft") self.setWindowIcon(QIcon("g-square.png")) self.createActions() self.createStatusBar() self.createMenus() self.createToolbars() self.createWidgets() self.createLayouts() def createActions(self): self.newAction = QAction("&New", self, shortcut=QKeySequence.New, statusTip="New") self.sendReceiveAction = QAction("Send / &Receive", self, shortcut="F9", statusTip="Send / Receive") self.printAction = QAction("&Print...", self, shortcut="Ctrl+P", statusTip="Print") self.quitAction = QAction("&Quit", self, shortcut="Ctrl+Q", statusTip="Quit", triggered=self.close) self.copyAction = QAction("&Copy", self, statusTip="Copy", shortcut=QKeySequence.Copy) self.deleteAction = QAction("&Delete", self, statusTip="Delete Message") self.nextAction = QAction("Next &Unread Message", self, shortcut="Ctrl+]", statusTip="Next unread message") self.previousAction = QAction("P&revious Unread Message", self, shortcut="Ctrl+[", statusTip="Previous unread message") self.replyAction = QAction("&Reply", self, shortcut="Ctrl+R", statusTip="Reply to sender", triggered=self.reply) self.replyToAllAction = QAction("Reply to &All", self, shortcut="Ctrl+Shift+R", statusTip="Reply to all", triggered=self.replyToAll) self.forwardAction = QAction("&Forward", self, shortcut="Ctrl+F", statusTip="Forward") self.junkAction = QAction("Junk", self, shortcut="Ctrl+J", statusTip="Mark as Junk") self.notJunkAction = QAction("Not junk", self, shortcut="Shift+Ctrl+J", statusTip="Mark as Not Junk") self.contentsAction = QAction("&Contents", self, statusTip="Help Contents", shortcut="F1", triggered=self.helpContents) self.aboutAction = QAction("&About", self, statusTip="About GuloMail", triggered=self.about) self.cancelAction = QAction("&Cancel", self, statusTip="Cancel") def createStatusBar(self): self.statusBar() def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.sendReceiveAction) self.fileMenu.addAction(self.printAction) self.fileMenu.addAction(self.quitAction) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.copyAction) self.editMenu.addAction(self.deleteAction) self.viewMenu = self.menuBar().addMenu("&View") self.folderMenu = self.menuBar().addMenu("F&older") self.messageMenu = self.menuBar().addMenu("&Message") self.goToMenu = self.messageMenu.addMenu("&Go To") self.goToMenu.addAction(self.nextAction) self.goToMenu.addAction(self.previousAction) self.messageMenu.addAction(self.replyAction) self.messageMenu.addAction(self.replyToAllAction) self.messageMenu.addAction(self.forwardAction) self.markAsMenu = self.messageMenu.addMenu("Mar&k as...") self.markAsMenu.addAction(self.junkAction) self.markAsMenu.addAction(self.notJunkAction) self.searchMenu = self.menuBar().addMenu("&Search") self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.contentsAction) self.helpMenu.addAction(self.aboutAction) def createToolbars(self): self.toolbar = self.addToolBar('Main Toolbar') self.toolbar.setMovable(False) self.toolbar.addAction(self.newAction) self.toolbar.addSeparator() self.toolbar.addAction(self.sendReceiveAction) self.toolbar.addSeparator() self.toolbar.addAction(self.replyAction) self.toolbar.addAction(self.replyToAllAction) self.toolbar.addAction(self.forwardAction) self.toolbar.addSeparator() self.toolbar.addAction(self.printAction) self.toolbar.addAction(self.deleteAction) self.toolbar.addAction(self.junkAction) self.toolbar.addAction(self.notJunkAction) self.toolbar.addAction(self.cancelAction) self.toolbar.addSeparator() self.toolbar.addAction(self.previousAction) self.toolbar.addAction(self.nextAction) def createWidgets(self): ## Message Table self.table = QTableView() self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setGridStyle(Qt.NoPen) self.model = QStandardItemModel(8, 3, self) self.model.setHeaderData(0, Qt.Horizontal, "From") self.model.setHeaderData(1, Qt.Horizontal, "Subject") self.model.setHeaderData(2, Qt.Horizontal, "Received") self.table.setModel(self.model) self.selectionModel = QItemSelectionModel(self.model) self.selectionModel.SelectionFlag = 0x0020 self.table.setSelectionModel(self.selectionModel) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setSortingEnabled(True) self.table.setAlternatingRowColors(True) ## Folder Tree View self.folderTree = QTreeWidget() self.folderTree.setColumnCount(1) self.folderTree.setHeaderLabel(QString('Folders')) self.treeItem = QTreeWidgetItem() self.treeItem.setText(0, 'Folders') self.inbox = QTreeWidgetItem() self.inbox.setText(0, 'Inbox') self.deletedItems = QTreeWidgetItem() self.deletedItems.setText(0, 'Deleted Items') self.drafts = QTreeWidgetItem() self.drafts.setText(0, 'Drafts') self.junk = QTreeWidgetItem() self.junk.setText(0, 'Junk') self.outbox = QTreeWidgetItem() self.outbox.setText(0, 'Outbox') self.sent = QTreeWidgetItem() self.sent.setText(0, 'Sent') self.treeItem.addChild(self.inbox) self.treeItem.addChild(self.deletedItems) self.treeItem.addChild(self.drafts) self.treeItem.addChild(self.junk) self.treeItem.addChild(self.outbox) self.treeItem.addChild(self.sent) self.folderTree.addTopLevelItem(self.treeItem) self.folderTree.expandAll() self.folderTree.setAnimated(True) self.folderTree.setMaximumWidth(150) ## Temp. placeholders self.textEdit = QTextEdit() self.textEdit2 = QTextEdit() def createLayouts(self): self.mainSplitter = QSplitter() self.setCentralWidget(self.mainSplitter) self.mainSplitter.addWidget(self.folderTree) self.messageSplitter = QSplitter(Qt.Vertical) self.messageSplitter.addWidget(self.table) self.messageSplitter.addWidget(self.textEdit2) self.mainSplitter.addWidget(self.messageSplitter) def helpContents(self): print "Help" def reply(self): print "Reply" def replyToAll(self): print "Reply To All" def about(self): text = QString("GuloMail v0.1\n\n") text.append( "GuloMail is a freeware email client written in Python using PyQt4 (Python bindings for Nokia's Qt)\n\n" ) text.append(QChar(0x00A9)) text.append("GulonSoft 2010\nhttp://www.gulon.co.uk/") QMessageBox.about(self, "About GuloMail", text)
class ChangedDocumentsListDialog(widgets.dialog.Dialog): def __init__(self): super(ChangedDocumentsListDialog, self).__init__(buttons=('close',)) self.setWindowModality(Qt.NonModal) self.setAttribute(Qt.WA_QuitOnClose, False) layout = QGridLayout(margin=0) self.mainWidget().setLayout(layout) self.tree = QTreeWidget(headerHidden=True, rootIsDecorated=False, columnCount=2, itemsExpandable=False) self.tree.setSelectionMode(QTreeWidget.ExtendedSelection) self.buttonReload = QPushButton() self.buttonReloadAll = QPushButton() self.buttonSave = QPushButton() self.buttonSaveAll = QPushButton() self.buttonShowDiff = QPushButton() self.checkWatchingEnabled = QCheckBox(checked=enabled()) layout.addWidget(self.tree, 0, 0, 6, 1) layout.addWidget(self.buttonReload, 0, 1) layout.addWidget(self.buttonReloadAll, 1, 1) layout.addWidget(self.buttonSave, 2, 1) layout.addWidget(self.buttonSaveAll, 3, 1) layout.addWidget(self.buttonShowDiff, 4, 1) layout.addWidget(self.checkWatchingEnabled, 6, 0, 1, 2) layout.setRowStretch(5, 10) app.documentClosed.connect(self.removeDocument) app.documentSaved.connect(self.removeDocument) app.documentUrlChanged.connect(self.removeDocument) app.documentLoaded.connect(self.removeDocument) self.tree.itemSelectionChanged.connect(self.updateButtons) self.buttonReload.clicked.connect(self.slotButtonReload) self.buttonReloadAll.clicked.connect(self.slotButtonReloadAll) self.buttonSave.clicked.connect(self.slotButtonSave) self.buttonSaveAll.clicked.connect(self.slotButtonSaveAll) self.buttonShowDiff.clicked.connect(self.slotButtonShowDiff) self.checkWatchingEnabled.toggled.connect(setEnabled) app.translateUI(self) qutil.saveDialogSize(self, 'externalchanges/dialog/size', QSize(400, 200)) userguide.addButton(self.buttonBox(), "externalchanges") self.button('close').setFocus() def translateUI(self): self.setWindowTitle(app.caption(_("Modified Files"))) self.setMessage(_( "The following files were modified or deleted by other " "applications:")) self.buttonReload.setText(_("Reload")) self.buttonReload.setToolTip(_( "Reloads the selected documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonReloadAll.setText(_("Reload All")) self.buttonReloadAll.setToolTip(_( "Reloads all externally modified documents from disk. " "(You can still reach the previous state of the document " "using the Undo command.)")) self.buttonSave.setText(_("Save")) self.buttonSave.setToolTip(_( "Saves the selected documents to disk, overwriting the " "modifications by another program.")) self.buttonSaveAll.setText(_("Save All")) self.buttonSaveAll.setToolTip(_( "Saves all documents to disk, overwriting the modifications by " "another program.")) self.buttonShowDiff.setText(_("Show Difference...")) self.buttonShowDiff.setToolTip(_( "Shows the differences between the current document " "and the file on disk.")) self.checkWatchingEnabled.setText(_( "Enable watching documents for external changes")) self.checkWatchingEnabled.setToolTip(_( "If checked, Frescobaldi will warn you when opened files are " "modified or deleted by other applications.")) def setDocuments(self, documents): """Display the specified documents in the list.""" # clear the treewidget for d in self.tree.invisibleRootItem().takeChildren(): for i in d.takeChildren(): i.doc = None # group the documents by directory dirs = {} for d in documents: path = d.url().toLocalFile() if path: dirname, filename = os.path.split(path) dirs.setdefault(dirname, []).append((filename, d)) for dirname in sorted(dirs, key=util.naturalsort): diritem = QTreeWidgetItem() diritem.setText(0, util.homify(dirname)) self.tree.addTopLevelItem(diritem) diritem.setExpanded(True) diritem.setFlags(Qt.ItemIsEnabled) diritem.setIcon(0, icons.get('folder-open')) for filename, document in sorted(dirs[dirname], key=lambda item: util.naturalsort(item[0])): fileitem = QTreeWidgetItem() diritem.addChild(fileitem) if documentwatcher.DocumentWatcher.instance(document).isdeleted(): itemtext = _("[deleted]") icon = "dialog-error" else: itemtext = _("[modified]") icon = "document-edit" fileitem.setIcon(0, icons.get(icon)) fileitem.setText(0, filename) fileitem.setText(1, itemtext) fileitem.doc = document # select the item if there is only one if len(dirs) == 1 and len(list(dirs.values())[0]) == 1: fileitem.setSelected(True) self.tree.resizeColumnToContents(0) self.tree.resizeColumnToContents(1) self.updateButtons() def removeDocument(self, document): """Remove the specified document from our list.""" for d in range(self.tree.topLevelItemCount()): diritem = self.tree.topLevelItem(d) for f in range(diritem.childCount()): if diritem.child(f).doc is document: i = diritem.takeChild(f) i.doc = None if diritem.childCount() == 0: self.tree.takeTopLevelItem(d) break else: continue break self.updateButtons() # hide if no documents are left if self.tree.topLevelItemCount() == 0: self.hide() def selectedDocuments(self): """Return the selected documents.""" return [i.doc for i in self.tree.selectedItems()] def allDocuments(self): """Return all shown documents.""" return [self.tree.topLevelItem(d).child(f).doc for d in range(self.tree.topLevelItemCount()) for f in range(self.tree.topLevelItem(d).childCount())] def updateButtons(self): """Updates the buttons regarding the selection.""" docs_sel = self.selectedDocuments() docs_all = self.allDocuments() all_deleted_sel = all(documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_sel) all_deleted_all = all(documentwatcher.DocumentWatcher.instance(d).isdeleted() for d in docs_all) self.buttonSave.setEnabled(len(docs_sel) > 0) self.buttonSaveAll.setEnabled(len(docs_all) > 0) self.buttonReload.setEnabled(not all_deleted_sel) self.buttonReloadAll.setEnabled(not all_deleted_all) self.buttonShowDiff.setEnabled(len(docs_sel) == 1 and not all_deleted_sel) def slotButtonReload(self): """Called when the user clicks Reload.""" self.reloadDocuments(self.selectedDocuments()) def slotButtonReloadAll(self): """Called when the user clicks Reload All.""" self.reloadDocuments(self.allDocuments()) def slotButtonSave(self): """Called when the user clicks Save.""" self.saveDocuments(self.selectedDocuments()) def slotButtonSaveAll(self): """Called when the user clicks Save All.""" self.saveDocuments(self.allDocuments()) def reloadDocuments(self, documents): """Used by slotButtonReload and slotButtonReloadAll.""" failures = [] for d in documents: try: d.load(keepUndo=True) except IOError as e: failures.append((d, e)) if failures: msg = _("Could not reload:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format( url = d.url().toLocalFile(), strerror = e.strerror, errno = e.errno) for d, e in failures) QMessageBox.critical(self, app.caption(_("Error")), msg) def saveDocuments(self, documents): """Used by slotButtonSave and slotButtonSaveAll.""" failures = [] for d in documents: try: d.save() except IOError as e: failures.append((d, e)) if failures: msg = _("Could not save:") + "\n\n" + "\n".join( "{url}: {strerror} ({errno})".format( url = d.url().toLocalFile(), strerror = e.strerror, errno = e.errno) for d, e in failures) + "\n\n" + \ _("Please save the document using the \"Save As...\" dialog.", "Please save the documents using the \"Save As...\" dialog.", len(failures)) QMessageBox.critical(self, app.caption(_("Error")), msg) def slotButtonShowDiff(self): """Called when the user clicks Show Difference.""" docs = self.selectedDocuments() or self.allDocuments() if not docs: return d = docs[0] if documentwatcher.DocumentWatcher.instance(d).isdeleted(): return filename = d.url().toLocalFile() try: with open(filename, 'rb') as f: disktext = util.decode(f.read()) except (IOError, OSError): return currenttext = d.toPlainText() html = htmldiff.htmldiff( currenttext, disktext, _("Current Document"), _("Document on Disk"), numlines=5) dlg = widgets.dialog.Dialog(self, buttons=('close',)) view = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap) view.setHtml(html) dlg.setMainWidget(view) dlg.setWindowTitle(app.caption("Differences")) dlg.setMessage(_( "Document: {url}\n" "Difference between the current document and the file on disk:").format( url=filename)) dlg.setWindowModality(Qt.NonModal) dlg.setAttribute(Qt.WA_QuitOnClose, False) dlg.setAttribute(Qt.WA_DeleteOnClose) qutil.saveDialogSize(dlg, "externalchanges/diff/dialog/size", QSize(600, 300)) dlg.show()
class PymetricsViewer( QWidget ): " Pymetrics tab widget " # Limits to colorize the McCabe score LittleRiskLimit = 10 ModerateRiskLimit = 20 HighRiskLimit = 50 # Options of providing a report SingleFile = 0 DirectoryFiles = 1 ProjectFiles = 2 SingleBuffer = 3 def __init__( self, parent = None ): QWidget.__init__( self, parent ) self.__reportUUID = "" self.__reportFileName = "" self.__reportOption = -1 self.__reportShown = False self.__report = None # Prepare members for reuse self.__noneLabel = QLabel( "\nNo results available" ) self.__noneLabel.setFrameShape( QFrame.StyledPanel ) self.__noneLabel.setAlignment( Qt.AlignHCenter ) self.__headerFont = self.__noneLabel.font() self.__headerFont.setPointSize( self.__headerFont.pointSize() + 4 ) self.__noneLabel.setFont( self.__headerFont ) self.__noneLabel.setAutoFillBackground( True ) noneLabelPalette = self.__noneLabel.palette() noneLabelPalette.setColor( QPalette.Background, GlobalData().skin.nolexerPaper ) self.__noneLabel.setPalette( noneLabelPalette ) self.__createLayout( parent ) self.__updateButtonsStatus() return def __createLayout( self, parent ): " Creates the toolbar and layout " # Buttons self.__mcCabeButton = QAction( PixmapCache().getIcon( 'tableview.png' ), 'Switch to McCabe only table view', self ) self.__mcCabeButton.setCheckable( True ) self.connect( self.__mcCabeButton, SIGNAL( 'toggled(bool)' ), self.__onMcCabe ) self.printButton = QAction( PixmapCache().getIcon( 'printer.png' ), 'Print', self ) #printButton.setShortcut( 'Ctrl+' ) self.connect( self.printButton, SIGNAL( 'triggered()' ), self.__onPrint ) self.printButton.setVisible( False ) self.printPreviewButton = QAction( PixmapCache().getIcon( 'printpreview.png' ), 'Print preview', self ) #printPreviewButton.setShortcut( 'Ctrl+' ) self.connect( self.printPreviewButton, SIGNAL( 'triggered()' ), self.__onPrintPreview ) self.printPreviewButton.setVisible( False ) spacer = QWidget() spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.clearButton = QAction( PixmapCache().getIcon( 'trash.png' ), 'Clear', self ) self.connect( self.clearButton, SIGNAL( 'triggered()' ), self.__clear ) # The toolbar self.toolbar = QToolBar( self ) self.toolbar.setOrientation( Qt.Vertical ) self.toolbar.setMovable( False ) self.toolbar.setAllowedAreas( Qt.RightToolBarArea ) self.toolbar.setIconSize( QSize( 16, 16 ) ) self.toolbar.setFixedWidth( 28 ) self.toolbar.setContentsMargins( 0, 0, 0, 0 ) self.toolbar.addAction( self.__mcCabeButton ) self.toolbar.addAction( self.printPreviewButton ) self.toolbar.addAction( self.printButton ) self.toolbar.addWidget( spacer ) self.toolbar.addAction( self.clearButton ) self.__totalResultsTree = QTreeWidget() self.__totalResultsTree.setAlternatingRowColors( True ) self.__totalResultsTree.setRootIsDecorated( True ) self.__totalResultsTree.setItemsExpandable( True ) self.__totalResultsTree.setUniformRowHeights( True ) self.__totalResultsTree.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) headerLabels = [ "Path / name", "Value", "" ] self.__totalResultsTree.setHeaderLabels( headerLabels ) self.connect( self.__totalResultsTree, SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ), self.__allItemActivated ) self.connect( self.__totalResultsTree, SIGNAL( "itemExpanded(QTreeWidgetItem *)" ), self.__onResultsExpanded ) self.__totalResultsTree.setColumnHidden( 2, True ) self.__totalResultsTree.hide() self.__mcCabeTable = QTreeWidget() self.__mcCabeTable.setAlternatingRowColors( True ) self.__mcCabeTable.setRootIsDecorated( False ) self.__mcCabeTable.setItemsExpandable( False ) self.__mcCabeTable.setSortingEnabled( True ) self.__mcCabeTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__mcCabeTable.setUniformRowHeights( True ) headerLabels = [ "", "File name", "Object", "McCabe Complexity" ] self.__mcCabeTable.setHeaderLabels( headerLabels ) self.connect( self.__mcCabeTable, SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ), self.__mcCabeActivated ) self.__mcCabeTable.hide() self.__hLayout = QHBoxLayout() self.__hLayout.setContentsMargins( 0, 0, 0, 0 ) self.__hLayout.setSpacing( 0 ) self.__hLayout.addWidget( self.toolbar ) self.__hLayout.addWidget( self.__noneLabel ) self.__hLayout.addWidget( self.__totalResultsTree ) self.__hLayout.addWidget( self.__mcCabeTable ) self.setLayout( self.__hLayout ) return def getTotalResultsWidget( self ): " Provides a reference to the total results widget " return self.__totalResultsTree def getMcCabeResultsWidget( self ): " Provides a reference to the McCabe results widget " return self.__mcCabeTable def __updateButtonsStatus( self ): " Updates the buttons status " self.__mcCabeButton.setEnabled( self.__reportShown ) self.printButton.setEnabled( self.__reportShown ) self.printPreviewButton.setEnabled( self.__reportShown ) self.clearButton.setEnabled( self.__reportShown ) return def __onResultsExpanded( self, item ): " An item has been expanded, so the column width should be adjusted " self.__totalResultsTree.header().resizeSections( QHeaderView.ResizeToContents ) return def __onPrint( self ): " Triggered when the print button is pressed " pass def __onPrintPreview( self ): " triggered when the print preview button is pressed " pass def __onMcCabe( self, state ): " Triggered when the metrics view is switched " if not self.__reportShown: return if state: self.__totalResultsTree.hide() self.__mcCabeTable.show() self.__mcCabeButton.setIcon( PixmapCache().getIcon( 'treeview.png' ) ) self.__mcCabeButton.setToolTip( "Switch to complete " "results tree view" ) else: self.__mcCabeTable.hide() self.__totalResultsTree.show() self.__mcCabeButton.setIcon( PixmapCache().getIcon( 'tableview.png' ) ) self.__mcCabeButton.setToolTip( "Switch to McCabe only table view" ) return def setFocus( self ): " Overridden setFocus " self.__hLayout.setFocus() return def __clear( self ): " Clears the content of the vertical layout " if not self.__reportShown: return self.__totalResultsTree.clear() self.__totalResultsTree.hide() self.__mcCabeTable.clear() self.__mcCabeTable.hide() self.__noneLabel.show() self.__report = None self.__reportShown = False self.__updateButtonsStatus() # self.resizeEvent() self.__mcCabeButton.setIcon( PixmapCache().getIcon( 'tableview.png' ) ) self.__mcCabeButton.setToolTip( "Switch to McCabe only table view" ) self.__mcCabeButton.setChecked( False ) self.__updateTooltip() return def __updateTooltip( self ): " Generates a signal with appropriate string message " if not self.__reportShown: tooltip = "No metrics available" elif self.__reportOption == self.DirectoryFiles: tooltip = "Metrics generated for directory: " + \ self.__reportFileName elif self.__reportOption == self.ProjectFiles: tooltip = "Metrics generated for the whole project" elif self.__reportOption == self.SingleFile: tooltip = "Metrics generated for file: " + self.__reportFileName elif self.__reportOption == self.SingleBuffer: tooltip = "Metrics generated for unsaved file: " + \ self.__reportFileName else: tooltip = "" self.emit( SIGNAL( 'updatePymetricsTooltip' ), tooltip ) return @staticmethod def __shouldShowFileName( table, column ): " Checks if the file name is the same " size = table.topLevelItemCount() if size == 0: return False index = size - 1 firstName = table.topLevelItem( index ).text( column ) index -= 1 while index >= 0: if table.topLevelItem( index ).text( column ) != firstName: return True index -= 1 return False def showReport( self, metrics, reportOption, fileName, uuid ): " Shows the pymetrics results " self.__clear() self.__noneLabel.hide() self.__report = metrics self.__reportUUID = uuid self.__reportFileName = fileName self.__reportOption = reportOption if len( metrics.report ) > 1: accumulatedBasic = self.__accumulateBasicMetrics() accItem = QTreeWidgetItem( [ "Cumulative basic metrics" ] ) self.__totalResultsTree.addTopLevelItem( accItem ) for key in accumulatedBasic: bmItem = [ BasicMetrics.metricsOfInterest[ key ], splitThousands( str( accumulatedBasic[ key ] ) ) ] basicMetric = QTreeWidgetItem( bmItem ) accItem.addChild( basicMetric ) # Add the complete information for fileName in metrics.report: if reportOption == self.SingleBuffer: fileItem = QTreeWidgetItem( [ "Editor buffer" ] ) else: fileItem = QTreeWidgetItem( [ fileName ] ) info = GlobalData().briefModinfoCache.get( fileName ) if info.docstring is not None: fileItem.setToolTip( 0, info.docstring.text ) else: fileItem.setToolTip( 0, "" ) self.__totalResultsTree.addTopLevelItem( fileItem ) # Messages part messages = metrics.report[ fileName ].messages if len( messages ) > 0: messagesItem = QTreeWidgetItem( [ "Messages" ] ) fileItem.addChild( messagesItem ) for message in messages: mItem = [ message, "", "E" ] messagesItem.addChild( QTreeWidgetItem( mItem ) ) # Basic metrics part basicItem = QTreeWidgetItem( [ "Basic metrics" ] ) fileItem.addChild( basicItem ) basic = metrics.report[ fileName ].basicMetrics for key in basic.metrics: bmItem = [ BasicMetrics.metricsOfInterest[ key ], str( basic.metrics[ key ] ) ] basicMetric = QTreeWidgetItem( bmItem ) basicItem.addChild( basicMetric ) # McCabe part mccabeItem = QTreeWidgetItem( [ "McCabe metrics" ] ) fileItem.addChild( mccabeItem ) mccabe = metrics.report[ fileName ].mcCabeMetrics.metrics for objName in mccabe: objItem = [ objName, str( mccabe[ objName ] ), "M" ] mccabeMetric = QTreeWidgetItem( objItem ) mccabeItem.addChild( mccabeMetric ) # COCOMO 2 part cocomo = [ "COCOMO 2", str( metrics.report[ fileName ].cocomo2Metrics.value ) ] cocomoItem = QTreeWidgetItem( cocomo ) fileItem.addChild( cocomoItem ) # Resizing the table self.__totalResultsTree.header().resizeSections( QHeaderView.ResizeToContents ) # Add McCabe complexity information for fileName in metrics.report: mccabe = metrics.report[ fileName ].mcCabeMetrics.metrics for objName in mccabe: values = [ "", fileName, objName, str( mccabe[ objName ] ) ] self.__mcCabeTable.addTopLevelItem( McCabeTableItem( values ) ) if not self.__shouldShowFileName( self.__mcCabeTable, 1 ): self.__mcCabeTable.setColumnHidden( 1, True ) # Resizing and sorting the table self.__mcCabeTable.header().setSortIndicator( 3, Qt.DescendingOrder ) self.__mcCabeTable.sortItems( 3, self.__mcCabeTable.header().sortIndicatorOrder() ) self.__mcCabeTable.header().resizeSections( QHeaderView.ResizeToContents ) # Show the complete information self.__mcCabeTable.hide() self.__totalResultsTree.show() self.__reportShown = True self.__updateButtonsStatus() self.__updateTooltip() # It helps, but why do I have flickering? QApplication.processEvents() return def __accumulateBasicMetrics( self ): " Accumulates basic metrics for all the processed files " basic = {} for fileName in self.__report.report: singleBasic = self.__report.report[ fileName ].basicMetrics.metrics for key in singleBasic: if not key.startswith( 'num' ): continue if key in basic: basic[ key ] += int( singleBasic[ key ] ) else: basic[ key ] = int( singleBasic[ key ] ) return basic def __mcCabeActivated( self, item, column ): " Handles the double click (or Enter) on the mccabe table item " objName = str( item.text( 2 ) ) if self.__reportOption == self.SingleBuffer: if os.path.isabs( self.__reportFileName ): fileName = self.__reportFileName else: fileName = "" else: fileName = str( item.text( 1 ) ) self.__onMcCabeObject( objName, fileName ) return def __allItemActivated( self, item, column ): " Handles the double click (or Enter) in the total results tree " # We process only the error messages and McCabe items hiddenColumnText = str( item.text( 2 ) ) if not hiddenColumnText in [ "M", "E" ]: return fileName = self.__getTreeItemFileName( item ) lineNumber = 0 if hiddenColumnText == "M": # This is McCabe item objName = str( item.text( 0 ) ) self.__onMcCabeObject( objName, fileName ) return elif hiddenColumnText == "E": # This is an error message message = str( item.text( 0 ) ) pos = message.find( "at line" ) if pos == -1: logging.error( "Unknown format of the message. " "Please inform the developers." ) return parts = message[ pos: ].split() try: lineNumber = int( parts[ 2 ].replace( ',', '' ) ) except: logging.error( "Unknown format of the message. " "Please inform the developers." ) return if fileName == "": # This is an unsaved buffer, try to find the editor by UUID mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetByUUID( self.__reportUUID ) if widget is None: logging.error( "The unsaved buffer has been closed" ) return # The widget was found, so jump to the required editor = widget.getEditor() editor.gotoLine( lineNumber ) editor.setFocus() return GlobalData().mainWindow.openFile( fileName, lineNumber ) return def __getTreeItemFileName( self, item ): " Identifies the tree view item file name " if self.__reportOption == self.SingleBuffer: if os.path.isabs( self.__reportFileName ): return self.__reportFileName return "" # The file name is always two levels up fileItem = item.parent().parent() return str( fileItem.text( 0 ) ) def __onMcCabeObject( self, objName, fileName ): " Called when the user activated McCabe item " info = None mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetByUUID( self.__reportUUID ) if widget is None: if fileName == "": logging.error( "The unsaved buffer has been closed" ) return # No widget, but we know the file name info = getBriefModuleInfoFromFile( fileName ) else: # The widget was found editor = widget.getEditor() # The editor content has been modified, so re-parse the buffer info = getBriefModuleInfoFromMemory( editor.text() ) parts = objName.split( '.' ) currentIndex = 0 functionsContainer = info.functions classesContainer = info.classes line = -1 if objName == "__main__" and len( parts ) == 1: # Special case - global file scope line = 1 currentIndex = 1 while currentIndex < len( parts ): found = False for func in functionsContainer: if func.name == parts[ currentIndex ]: if currentIndex == len( parts ) - 1: # Found, jump to the line line = func.line break functionsContainer = func.functions classesContainer = func.classes found = True break if line != -1: break if found: currentIndex += 1 continue for klass in classesContainer: if klass.name == parts[ currentIndex ]: if currentIndex == len( parts ) - 1: # Found, jump to the line line = klass.line break functionsContainer = klass.functions classesContainer = klass.classes found = True if line != -1: break if found: currentIndex += 1 continue # Not found logging.error( "Cannot find the " + objName ) return # Here we have the line number if widget is None: GlobalData().mainWindow.openFile( fileName, line ) else: editor = widget.getEditor() editor.gotoLine( line ) editor.setFocus() return def onFileUpdated( self, fileName, uuid ): " Called when a buffer is saved or saved as " if not self.__reportShown: return if self.__reportUUID != uuid: return # Currently shown report is for the saved buffer # File name is expected being absolute self.__reportFileName = fileName self.emit( SIGNAL( 'updatePymetricsTooltip' ), "Metrics generated for buffer saved as " + fileName ) return
class DBServersWidget(QWidget): """Displays a list of servers""" def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.connections = {} self.setWindowTitle("Servers") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(True) self.tree.setHeaderLabels(["Server", "Butt"]) # set header, but hide anyway self.tree.header().hide() self.tree.header().setResizeMode(C.node, QHeaderView.Stretch) self.tree.setColumnWidth(C.butt, 20) self.connect(self.tree, SIGNAL('itemSelectionChanged()'), self.on_tree_selection_changed) self.connect(self.tree, SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'), self.on_tree_double_clicked) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers() #======================================= ##== Tree Events def on_tree_selection_changed(self): disabled = self.tree.selectionModel().hasSelection() == False self.actionServerEdit.setDisabled(disabled) self.actionServerDelete.setDisabled(disabled) def on_tree_double_clicked(self): self.actionServerEdit.trigger() #======================================= ## Server Actions def on_server_add(self): self.show_server_dialog(None) def on_server_edit(self): item = self.tree.currentItem() if item == None: return server = str(item.text(C.server)) self.show_server_dialog(server) def show_server_dialog(self, server=None): d = DBServerDialog.DBServerDialog(self, server) if d.exec_(): self.load_servers() def load_servers(self): """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """ self.tree.clear() for butt in self.buttGroup.buttons(): self.buttGroup.removeButton(butt) for srv in G.settings.get_servers_list(): item = QTreeWidgetItem() item.setText(C.node, srv['server']) #item.setText(C.user, srv['user']) self.tree.addTopLevelItem(item) butt = QToolButton() butt.setIcon(Ico.icon(Ico.Connect)) butt.setProperty("server", srv['server']) self.tree.setItemWidget(item, C.butt, butt) self.buttGroup.addButton(butt) def on_server_delete(self): item = self.tree.currentItem() if item == None: return srv = str(item.text(C.server)) G.settings.delete_server(srv) self.load_servers() def on_open_server(self, butt): # self.emit(SIGNAL("open_server"), butt.property("server").toString()) srv_ki = str(butt.property("server").toString()) server = G.settings.get_server(srv_ki) db = QSqlDatabase.addDatabase("QMYSQL", srv_ki) db.setHostName(server['server']) db.setUserName(server['user']) db.setPassword(server['passwd']) ok = db.open() if ok: #self.connections[srv_ki] = self.load_databases(srv_ki) print "open", ok def load_databases(self, srv_ki): """Load databases into tree node for server; executes 'show databases;' or aslike """ sql = "show databases;" query = QSqlQuery(QSqlDatabase.database(srv_ki)) ok = query.exec_(sql) print ok, sql, query.result() # Get the parent node, ie the server node pItem = self.tree.findItems(srv_ki, Qt.MatchExactly, C.node)[0] ## Assumed value(0) is the table.. we need the defs (ie mysql case) while query.next(): table_name = query.value(0).toString() nuItem = QTreeWidgetItem(pItem) nuItem.setText(C.node, table_name) #print table_name self.tree.setItemExpanded(pItem, True)
def __createLayout(self, action, title, files): """ Creates the dialog layout """ self.resize(400, 300) self.setSizeGripEnabled(True) # Top level layout layout = QVBoxLayout(self) # Pixmap and the message topLayout = QHBoxLayout() pixmap = QLabel() pixmap.setPixmap(PixmapCache().getPixmap('warning.png')) topLayout.addWidget(pixmap) hSpacer = QWidget() hSpacer.setFixedSize(15, 15) topLayout.addWidget(hSpacer) message = QLabel( "All the project files must be " \ "saved before start debugging" ) message.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) message.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) message.setWordWrap(True) topLayout.addWidget(message) layout.addLayout(topLayout) vSpacer = QWidget() vSpacer.setFixedSize(15, 15) layout.addWidget(vSpacer) layout.addWidget(QLabel(title + ":")) filesList = QTreeWidget() filesList.setRootIsDecorated(False) filesList.setAlternatingRowColors(True) filesList.setUniformRowHeights(True) filesList.setItemsExpandable(False) filesList.setItemDelegate(NoOutlineHeightDelegate(4)) filesList.setSelectionMode(QAbstractItemView.NoSelection) filesList.setHeaderHidden(True) for item in files: fileName = item[0] fileItem = QTreeWidgetItem([fileName]) fileType = detectFileType(fileName) fileItem.setIcon(0, getFileIcon(fileType)) if fileType in [PythonFileType, Python3FileType]: infoSrc = GlobalData().briefModinfoCache info = infoSrc.get(fileName) if info.docstring is not None: fileItem.setToolTip(0, info.docstring.text) else: fileItem.setToolTip(0, "") filesList.addTopLevelItem(fileItem) layout.addWidget(filesList) # Buttons at the bottom buttonBox = QDialogButtonBox() buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Cancel) continueButton = buttonBox.addButton(action, QDialogButtonBox.ActionRole) continueButton.setDefault(True) layout.addWidget(buttonBox) continueButton.clicked.connect(self.accept) buttonBox.rejected.connect(self.close) continueButton.setFocus() return
class MainWindow(QtGui.QMainWindow): sig_update_tree = pyqtSignal(object, object, object) sig_show_overview_plot = pyqtSignal() def __init__(self, font, parent=None): super(MainWindow, self).__init__(parent) self.font = font self.setWindowTitle("Meridien") central_widget = QtGui.QWidget(self) self.setCentralWidget(central_widget) #Center on screen resolution = QtGui.QDesktopWidget().screenGeometry() self.move((resolution.width() / 2) - (self.frameSize().width() / 2), (resolution.height() / 2) - (self.frameSize().height() / 2)) """ Setting up menu bar """ close_action = QtGui.QAction('Close', self) close_action.setShortcut("Ctrl+Q") close_action.setStatusTip('Leave the app') close_action.triggered.connect(lambda: self.close()) open_refinement_folder = QtGui.QAction('Open Refinement Folder', self) open_refinement_folder.triggered.connect(self.open_refinement_folder) self.mainMenu = self.menuBar() self.fileMenu = self.mainMenu.addMenu('&File') self.fileMenu.addAction(open_refinement_folder) self.fileMenu.addAction(close_action) self.refinement_folder = "" create_new_fsc_plot = QtGui.QAction('&New FSC plot', self) create_new_fsc_plot.triggered.connect( self.event_ontriggered_show_fsc_plot) create_new_overview_plot = QtGui.QAction( '&New resolution overview plot', self) create_new_overview_plot.triggered.connect( self.event_show_resolution_overview_plot) self.plotMenu = self.mainMenu.addMenu('&Plot') self.plotMenu.addAction(create_new_fsc_plot) self.plotMenu.addAction(create_new_overview_plot) """ Setup other components """ self.layout = QGridLayout(central_widget) self.setMenuBar(self.mainMenu) self.tree = QTreeWidget(self) self.tree.setHeaderHidden(True) self.layout.addWidget(self.tree, 1, 0) self.root_items_path_dictionary = {} # Threads self.threadpool = QThreadPool() self.thread_list = [] thr = QThread(self) thr.start() self.reader = DriverFileReader() self.reader.moveToThread(thr) self.thread_list.append(thr) self.timer = QTimer(self) # Connect signals self.reader.sig_sendfolders.connect(self.fill_tree) self.reader.sig_sendfsc.connect(self.show_dialog_fsc) self.tree.itemChanged.connect(self._event_select_deselect_all) self.sig_update_tree.connect(self.update_tree) self.sig_show_overview_plot.connect( self.event_show_resolution_overview_plot) self.show() self.open_refinement_folder() self.monitor = None @pyqtSlot(object, object, object) def update_tree(self, item, monitored_folder, delete): ''' :param item: main folder to add to tree item belonging to folder montiored_folder :param monitored_folder: Refinement folder :param delete: if this is true, it will delete the monitored folder :return: ''' if delete: root = self.root_items_path_dictionary[monitored_folder] index = self.tree.indexOfTopLevelItem(root) self.tree.takeTopLevelItem(index) else: root = self.root_items_path_dictionary[monitored_folder] root.addChild(item) msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("Meridien - There is data of a new run: " + str(item.text(0))) msg.setWindowTitle("Update") msg.exec_() @pyqtSlot(object, object, object, object) def show_dialog_fsc(self, *args): """ Shows fsc plot :param args: list of arguments :return: None """ fsc_plot = FSCPlot(self) fsc_plot.plot(*args) @pyqtSlot() def event_show_resolution_overview_plot(self): """ Trigger for fsc plot :return: None """ tracker_reader = TrackerFileReader() res_0143, res_05 = tracker_reader.read_res0143_and_res05( self.refinement_folder) res_plot = ResolutionOverviewPlot(parent=self) res_plot.setWindowTitle(self.refinement_folder) res_plot.plot(res_05, res_0143) def event_ontriggered_show_fsc_plot(self): """ Trigger for fsc plot :return: none """ checked_runs = self._get_checked_items() paths = [] for checked_run in checked_runs: refinement_folder = checked_run.parent().text(0) path = os.path.join(str(refinement_folder), str(checked_run.text(0))) paths.append(path) self.reader.sig_readfsc.emit(paths) def _event_select_deselect_all(self, root_tree_item): ''' Checks all childs of root_tree_item :param root_tree_item: QTreeWidgetItem which represents a refinement folder :return: ''' if root_tree_item in self.root_items_path_dictionary.values(): number_of_runs = root_tree_item.childCount() for i in range(number_of_runs): child_run = root_tree_item.child(i) child_run.setCheckState(0, root_tree_item.checkState(0)) def _get_checked_items(self): """ Finds the checked elements in tree :return: List of checked QItemWidget """ checked_runs = [] for root in self.root_items_path_dictionary.values(): number_of_runs = root.childCount() for i in range(number_of_runs): main_run = root.child(i) if main_run.checkState(0) == QtCore.Qt.Checked: checked_runs.append(main_run) return checked_runs def open_refinement_folder(self): """ Let the user choose the refinement folder and adds it to the RefinementFolder-Tree :return: none """ self.refinement_folder = str( QtGui.QFileDialog.getExistingDirectory( self, "Select Refinement Directory")) if self.refinement_folder == "": return if self.refinement_folder in self.root_items_path_dictionary: return self._open_refinement_folder(self.refinement_folder) self.sig_show_overview_plot.emit() def _open_refinement_folder(self, path): """ Reads the refinement folder, setup the folder daemon and signals :param path: Path to refinement folder """ if path != '': #for i in reversed(range(self.root.childCount())): # self.root.removeChild(self.root.child(i)) name = os.path.basename(path) qname = QString(name) root = QtGui.QTreeWidgetItem([str(path)]) self.root_items_path_dictionary[str(path)] = root self.tree.addTopLevelItem(root) fm = QFontMetrics(self.font) w = fm.width(path) self.tree.setMinimumWidth(w + 150) #self.root.setText(0, qname) self.reader.sig_readfolders.emit(path) self.monitor = MonitorRefinementFolder(path, self.sig_update_tree, self) self.timer = QTimer(self) self.timer.timeout.connect(self.monitor.update) self.timer.start(2000) def closeEvent(self, close_event): ''' Closes all threads. ''' for thr in self.thread_list: thr.quit() thr.wait() @pyqtSlot(object) def fill_tree(self, path_to_refinement_folder): ''' Reads all runs in path_to_refinement_folder and add them as child to the corresponding root element in the tree :param path_to_refinement_folder: Path to refinement folder :return: none ''' root = self.root_items_path_dictionary[str(path_to_refinement_folder)] root.setCheckState(0, QtCore.Qt.Unchecked) main_dicts = DriverFileReader.read_refinement_folders( path_to_refinement_folder) for dictionary in main_dicts: next_item = QtGui.QTreeWidgetItem([dictionary]) next_item.setCheckState(0, QtCore.Qt.Unchecked) root.addChild(next_item) def close_application(self): ''' Close the application :return: none ''' sys.exit()
class Shortcuts(preferences.Page): def __init__(self, dialog): super(Shortcuts, self).__init__(dialog) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.scheme = SchemeSelector(self) layout.addWidget(self.scheme) self.tree = QTreeWidget(self) self.tree.setHeaderLabels([_("Command"), _("Shortcut")]) self.tree.setRootIsDecorated(False) self.tree.setColumnCount(2) self.tree.setAllColumnsShowFocus(True) self.tree.setAnimated(True) layout.addWidget(self.tree) self.edit = QPushButton(icons.get("preferences-desktop-keyboard-shortcuts"), '') layout.addWidget(self.edit) # signals self.scheme.currentChanged.connect(self.slotSchemeChanged) self.scheme.changed.connect(self.changed) self.tree.currentItemChanged.connect(self.slotCurrentItemChanged) self.tree.itemDoubleClicked.connect(self.editCurrentItem) self.edit.clicked.connect(self.editCurrentItem) # make a dict of all actions with the actions as key and the names as # value, with the collection prepended (for loading/saving) win = dialog.parent() allactions = {} for collection in actioncollectionmanager.manager(win).actionCollections(): for name, action in collection.actions().items(): allactions[action] = (collection, name) # keep a list of actions not in the menu structure left = allactions.keys() def add_actions(menuitem, actions): """Add actions to a QTreeWidgetItem.""" for a in actions: if a.menu(): item = build_menu_item(a) if item.childCount(): menuitem.addChild(item) elif a in left: left.remove(a) menuitem.addChild(ShortcutItem(a, *allactions[a])) menuitem.setFlags(Qt.ItemIsEnabled) # disable selection def build_menu_item(action): """Return a QTreeWidgetItem with children for all the actions in the submenu.""" menuitem = QTreeWidgetItem() text = qutil.removeAccelelator(action.text()) menuitem.setText(0, _("Menu {name}").format(name=text)) add_actions(menuitem, action.menu().actions()) return menuitem # present the actions nicely ordered as in the menus for a in win.menuBar().actions(): menuitem = build_menu_item(a) if menuitem.childCount(): self.tree.addTopLevelItem(menuitem) # sort leftover actions left.sort(key=lambda i: i.text()) # show actions that are left, grouped by collection titlegroups = {} for a in left[:]: # copy collection, name = allactions[a] if collection.title(): titlegroups.setdefault(collection.title(), []).append(a) left.remove(a) for title in sorted(titlegroups): item = QTreeWidgetItem(["{0}:".format(title)]) for a in titlegroups[title]: item.addChild(ShortcutItem(a, *allactions[a])) self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection # show other actions that were not in the menus item = QTreeWidgetItem([_("Other commands:")]) for a in left: if a.text() and not a.menu(): item.addChild(ShortcutItem(a, *allactions[a])) if item.childCount(): self.tree.addTopLevelItem(item) item.setFlags(Qt.ItemIsEnabled) # disable selection self.tree.expandAll() item = self.tree.topLevelItem(0).child(0) if _lastaction: # find the previously selected item for i in self.items(): if i.name == _lastaction: item = i break self.tree.setCurrentItem(item) self.tree.resizeColumnToContents(0) def items(self): """Yield all the items in the actions tree.""" def children(item): for i in range(item.childCount()): c = item.child(i) if c.childCount(): for c1 in children(c): yield c1 else: yield c for c in children(self.tree.invisibleRootItem()): yield c def saveSettings(self): self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts") for item in self.items(): for scheme in self.scheme.schemes(): item.save(scheme) item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def loadSettings(self): self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes") # clear the settings in all the items for item in self.items(): item.clearSettings() item.switchScheme(self.scheme.currentScheme()) def slotSchemeChanged(self): """Called when the Scheme combobox is changed by the user.""" for item in self.items(): item.switchScheme(self.scheme.currentScheme()) def slotCurrentItemChanged(self, item): if isinstance(item, ShortcutItem): self.edit.setText( _("&Edit Shortcut for \"{name}\"").format(name=item.text(0))) self.edit.setEnabled(True) global _lastaction _lastaction = item.name else: self.edit.setText(_("(no shortcut)")) self.edit.setEnabled(False) def editCurrentItem(self): item = self.tree.currentItem() if not isinstance(item, ShortcutItem): return try: dlg = self._editdialog except AttributeError: dlg = self._editdialog = ShortcutEditDialog(self) scheme = self.scheme.currentScheme() action = item.action(scheme) default = item.defaultShortcuts() if dlg.editAction(action, default): shortcuts = action.shortcuts() # check for conflicts conflicting = [] for i in self.items(): if i is not item: for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts): if s1.matches(s2) or s2.matches(s1): conflicting.append(i) if conflicting: # show a question dialog msg = [_("This shortcut conflicts with the following command:", "This shortcut conflicts with the following commands:", len(conflicting))] msg.append('<br/>'.join(i.text(0) for i in conflicting)) msg.append(_("Remove the shortcut from that command?", "Remove the shortcut from those commands?", len(conflicting))) msg = '<p>{0}</p>'.format('</p><p>'.join(msg)) res = QMessageBox.warning(self, _("Shortcut Conflict"), msg, QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if res == QMessageBox.Yes: # remove from conflicting for i in conflicting: l = i.shortcuts(scheme) for s1 in list(l): # copy for s2 in shortcuts: if s1.matches(s2) or s2.matches(s1): l.remove(s1) i.setShortcuts(l, scheme) elif res == QMessageBox.No: # remove from ourselves for i in conflicting: for s1 in list(shortcuts): # copy for s2 in i.shortcuts(scheme): if s1.matches(s2) or s2.matches(s1): shortcuts.remove(s1) else: return # cancelled # store the shortcut item.setShortcuts(shortcuts, scheme) self.changed.emit()
def __createLayout( self, action, title, files ): """ Creates the dialog layout """ self.resize( 400, 300 ) self.setSizeGripEnabled( True ) # Top level layout layout = QVBoxLayout( self ) # Pixmap and the message topLayout = QHBoxLayout() pixmap = QLabel() pixmap.setPixmap( PixmapCache().getPixmap( 'warning.png' ) ) topLayout.addWidget( pixmap ) hSpacer = QWidget() hSpacer.setFixedSize( 15, 15 ) topLayout.addWidget( hSpacer ) message = QLabel( "All the project files must be " \ "saved before start debugging" ) message.setAlignment( Qt.AlignHCenter | Qt.AlignVCenter ) message.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) message.setWordWrap( True ) topLayout.addWidget( message ) layout.addLayout( topLayout ) vSpacer = QWidget() vSpacer.setFixedSize( 15, 15 ) layout.addWidget( vSpacer ) layout.addWidget( QLabel( title + ":" ) ) filesList = QTreeWidget() filesList.setRootIsDecorated( False ) filesList.setAlternatingRowColors( True ) filesList.setUniformRowHeights( True ) filesList.setItemsExpandable( False ) filesList.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) filesList.setSelectionMode( QAbstractItemView.NoSelection ) filesList.setHeaderHidden( True ) for item in files: fileName = item[ 0 ] fileItem = QTreeWidgetItem( [ fileName ] ) fileType = detectFileType( fileName ) fileItem.setIcon( 0, getFileIcon( fileType ) ) if fileType in [ PythonFileType, Python3FileType ]: infoSrc = GlobalData().briefModinfoCache info = infoSrc.get( fileName ) if info.docstring is not None: fileItem.setToolTip( 0, info.docstring.text ) else: fileItem.setToolTip( 0, "" ) filesList.addTopLevelItem( fileItem ) layout.addWidget( filesList ) # Buttons at the bottom buttonBox = QDialogButtonBox() buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Cancel ) continueButton = buttonBox.addButton( action, QDialogButtonBox.ActionRole ) continueButton.setDefault( True ) layout.addWidget( buttonBox ) continueButton.clicked.connect( self.accept ) buttonBox.rejected.connect( self.close ) continueButton.setFocus() return