Exemple #1
0
class Window(QMainWindow):
    def __init__(self,parent = None):
        QMainWindow.__init__(self,parent)
        self.resize(1024,768)
        self.setWindowTitle("Sabel")
        self.setWindowIcon(Icons.sabel)
        self.centralwidget = QWidget(self)
        self.horizontalLayout = QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setMargin(0)
        self.cmdList = config.cmds()
        self.paramList = config.params()
        
        '''A.Editor TabWidget'''
        '''This parent is for findbar and vertical layout'''
        self.editorLayoutWidget = QWidget(self)
        self.editorLayoutWidget.setMinimumWidth(800)
        self.tabWidget = EditorTab(self)
        self.editorLayout = QVBoxLayout(self.editorLayoutWidget)
        self.editorLayout.setMargin(0)
        self.editorLayout.addWidget(self.tabWidget)
        
        "0.Style Layout"
        self.styleLayoutWidget = QFrame()
        self.styleLayoutWidget.setFrameShape(QFrame.StyledPanel)
        self.styleLayout = QHBoxLayout(self.styleLayoutWidget)
        self.styleTest = QPushButton(self.styleLayoutWidget)
        self.styleTest.setText("Change Styles")
        self.styleTest.clicked.connect(self.changeStyleSheet)
        self.popWidget = Popup(self.styleLayoutWidget)
        self.styleLayout.addWidget(self.styleTest)
        self.styleLayout.addWidget(self.popWidget)
        self.styleLayout.setMargin(0)
        self.editorLayout.addWidget(self.styleLayoutWidget)
        self.styleLayoutWidget.hide()
        
        "1.Find Layout"
        self.findLayoutWidget = QFrame()
        self.findLayoutWidget.setFrameShape(QFrame.StyledPanel)
        self.findLayout = QHBoxLayout(self.findLayoutWidget)
        self.lineEdit = QLineEdit(self.findLayoutWidget)
        self.lineEdit_2 = QLineEdit(self.findLayoutWidget)
        self.findClose = QPushButton(self.findLayoutWidget)
        self.findClose.setIcon(Icons.close_view)
        self.findClose.setFlat(True)
        self.findClose.clicked.connect(self.findBarShow)
        self.find = QPushButton(self.findLayoutWidget)
        self.find.setText("Find")
        self.find.clicked.connect(self.findCurrentText)
        self.replacefind = QPushButton(self.findLayoutWidget)
        self.replacefind.setText("Replace/Find")
        self.replacefind.clicked.connect(self.replaceFindText)
        self.replace = QPushButton(self.findLayoutWidget)
        self.replace.setText("Replace")
        self.replace.clicked.connect(self.replaceCurrentText)
        self.replaceAll = QPushButton(self.findLayoutWidget)
        self.replaceAll.setText("Replace All")
        self.replaceAll.clicked.connect(self.replaceAllText)
        self.caseSensitive = QToolButton(self.findLayoutWidget)
        self.caseSensitive.setIcon(Icons.font)
        self.caseSensitive.setCheckable(True)
        self.wholeWord = QToolButton(self.findLayoutWidget)
        self.wholeWord.setText("ww")
        self.wholeWord.setCheckable(True)
        self.regex = QToolButton(self.findLayoutWidget)
        self.regex.setText("re")
        self.regex.setCheckable(True)
        self.backward = QToolButton(self.findLayoutWidget)
        self.backward.setText("bk")
        self.backward.setCheckable(True)
        self.backward.setDisabled(True)
        self.findLayout.addWidget(self.findClose)
        self.findLayout.addWidget(self.find)
        self.findLayout.addWidget(self.lineEdit)
        self.findLayout.addWidget(self.lineEdit_2)
        self.findLayout.addWidget(self.caseSensitive)
        self.findLayout.addWidget(self.wholeWord)
        self.findLayout.addWidget(self.regex)
        self.findLayout.addWidget(self.backward)
        self.findLayout.addWidget(self.replacefind)
        self.findLayout.addWidget(self.replace)
        self.findLayout.addWidget(self.replaceAll)
        self.findLayout.setMargin(0)
        self.findLayoutWidget.setMaximumHeight(25)
        self.editorLayout.addWidget(self.findLayoutWidget)
        self.findLayoutWidget.hide()
        
        
        '''B.Designer'''
        '''This parent is for widgetsbar and design layout'''
        self.designerLayoutWidget = QWidget(self)
        self.designerLayoutWidget.setMinimumWidth(800)
        self.designerWidget = Screen(self)
        self.designerLayoutWidget.hide()
        self.designerLayout = QVBoxLayout(self.designerLayoutWidget)
        self.designerLayout.setMargin(0)
        self.designerLayout.addWidget(self.designerWidget)
        
        '''C.Level Editor'''
        '''This parent is for spritesheets and level layout'''
        self.levelLayoutWidget = QWidget(self)
        self.levelLayoutWidget.setMinimumWidth(800)
        self.levelWidget = Level(self)
        self.levelLayoutWidget.hide()
        self.levelLayout = QVBoxLayout(self.levelLayoutWidget)
        self.levelLayout.setMargin(0)
        self.levelLayout.addWidget(self.levelWidget)
        
        '''D.Explorer TabWidget'''
        self.explorerTabWidget = TreeTab(self)
        #self.explorerTabWidget.setMaximumWidth(200)
        '''1.Project Tree'''
        self.tab_5 = QWidget()
        #self.tab_5.setMaximumWidth(200)
        self.VerticalLayout_2 = QVBoxLayout(self.tab_5)#QHBoxLayout(self.tab_5)
        self.VerticalLayout_2.setMargin(0)
        self.treeWidget = ProjectTree(self.tab_5)
        #self.treeWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        #self.treeWidget.horizontalScrollBar().show()
        self.VerticalLayout_2.addWidget(self.treeWidget)
        
        '''2.Outline Tree'''
        self.tab_2 = QWidget()
        #self.tab_2.setMaximumWidth(200)
        self.VerticalLayout_3 = QVBoxLayout(self.tab_2)
        self.VerticalLayout_3.setMargin(0)
        self.outlineWidget = OutlineTree(self.tab_2)
        self.outlineWidget.itemDoubleClicked.connect(self.gotoLine)
        self.VerticalLayout_3.addWidget(self.outlineWidget)
        
        '''E.Output TabWidget'''
        self.outputTabWidget = OutputTab(self)
        self.tabWidget.currentChanged.connect(self.fileChanged)
        self.explorerTabWidget.currentChanged.connect(self.closeExplorer)
        self.outputTabWidget.currentChanged.connect(self.closeConsole)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.setTabShape(0)
            
        '''1.Output layout'''
        #must check
        self.tab_6 = QWidget()
        self.horizontalLayout_2 = QVBoxLayout(self.tab_6)
        self.horizontalLayout_2.setMargin(0)
        self.textEdit = QTextEdit()
        self.inputLayout = QHBoxLayout()
        self.inputLayout.setMargin(0)
        self.fileButton = QPushButton()
        self.fileButton.setText("File")
        self.fileButton.clicked.connect(self.getFile)
        self.runButton = QPushButton()
        self.runButton.setFlat(True)
        self.runButton.setIcon(Icons.go)
        self.combo = QComboBox()
        self.combo.setFixedWidth(100)
        self.comboAdd = QPushButton()
        self.comboAdd.setIcon(Icons.add)
        self.comboAdd.setFlat(True)
        self.comboAdd.clicked.connect(self.addCmd)
        self.comboDel = QPushButton()
        self.comboDel.setIcon(Icons.close_view)
        self.comboDel.setFlat(True)
        self.comboDel.clicked.connect(self.delCmd)
        self.combo2 = QComboBox()
        self.combo2.setFixedWidth(500)
        self.combo2Add = QPushButton()
        self.combo2Add.setIcon(Icons.add)
        self.combo2Add.setFlat(True)
        self.combo2Add.clicked.connect(self.addParam)
        self.combo2Del = QPushButton()
        self.combo2Del.setIcon(Icons.close_view)
        self.combo2Del.setFlat(True)
        self.combo2Del.clicked.connect(self.delParam)
        if(self.checkHasValue(self.cmdList)):
            for cmd in self.cmdList:
                self.combo.addItem(cmd)
        else:
            self.cmdList = []
        if(self.checkHasValue(self.paramList)):
            for param in self.paramList:
                self.combo2.addItem(param)
        else:
            self.paramList = []
        
        self.horizontalLayout_2.addWidget(self.textEdit)
        self.inputLayout.addWidget(QLabel("<b>Command:</b>"))
        self.inputLayout.addWidget(self.combo)
        self.inputLayout.addWidget(self.comboAdd)
        self.inputLayout.addWidget(self.comboDel)
        self.inputLayout.addWidget(QLabel("<b>Parameters:</b>"))
        self.inputLayout.addWidget(self.combo2)
        self.inputLayout.addWidget(self.combo2Add)
        self.inputLayout.addWidget(self.combo2Del)
        self.inputLayout.addWidget(self.fileButton)
        self.inputLayout.addWidget(self.runButton)
        self.horizontalLayout_2.addLayout(self.inputLayout)
        
        '''2.Error Layout'''
        self.tab_7 = QWidget()
        self.horizontalLayout_4 = QHBoxLayout(self.tab_7)
        self.horizontalLayout_4.setMargin(0)
        self.errorTree = ErrorTree(self.tab_7)
        self.errorTree.itemDoubleClicked.connect(self.errorLine)
        self.horizontalLayout_4.addWidget(self.errorTree)
        
        '''TabWidgets tabs'''
        #self.designerWidget.addTab(QWidget(self),"")
        #self.designerWidget.setTabIcon(0,Icons.close_view)
        #self.levelWidget.addTab(QWidget(self),"")
        #self.levelWidget.setTabIcon(0,Icons.close_view)
        
        self.explorerTabWidget.addTab(self.tab_5,"Projects")
        self.explorerTabWidget.addTab(self.tab_2,"Outline")
        self.explorerTabWidget.addTab(QWidget(self),"")
        self.explorerTabWidget.setTabIcon(0,Icons.cprj)
        self.explorerTabWidget.setTabIcon(1,Icons.envvar)
        self.explorerTabWidget.setTabIcon(2,Icons.close_view)
        self.outputTabWidget.addTab(self.tab_7,"Error")
        self.outputTabWidget.addTab(self.tab_6,"Output")
        self.outputTabWidget.addTab(QWidget(self),"")
        self.outputTabWidget.setTabIcon(0,Icons.error)
        self.outputTabWidget.setTabIcon(1,Icons.console_view)
        self.outputTabWidget.setTabIcon(2,Icons.close_view)
        
        '''Splitters'''
        self.split1 = QSplitter(Qt.Horizontal)
        self.split1.addWidget(self.explorerTabWidget)
        self.split1.addWidget(self.editorLayoutWidget)
        self.split1.addWidget(self.designerLayoutWidget)
        self.split1.addWidget(self.levelLayoutWidget)
        #self.split1.addWidget(self.tab_5)
        
        self.split2 = QSplitter(Qt.Vertical)
        self.split2.addWidget(self.split1)
        self.split2.addWidget(self.outputTabWidget)
        self.horizontalLayout.addWidget(self.split2)
        
        
        '''Status Bar'''
        self.statusbar = QStatusBar(self)
        self.aboutButton = QPushButton(self)
        self.aboutButton.setFlat(True)
        self.aboutButton.setIcon(Icons.anchor)
        self.aboutButton.clicked.connect(self.about)
        self.expButton = QPushButton(self)
        self.expButton.setFlat(True)
        self.expButton.setIcon(Icons.prj)
        self.expButton.clicked.connect(self.exp)
        self.cmdButton = QPushButton(self)
        self.cmdButton.setFlat(True)
        self.cmdButton.setIcon(Icons.console_view)
        self.cmdButton.clicked.connect(self.cmd)
        self.cmdButton.setShortcut('Ctrl+D')
        self.imgButton = QPushButton(self)
        self.imgButton.setFlat(True)
        self.imgButton.setIcon(Icons.color_palette)
        self.imgButton.clicked.connect(self.design)
        self.imgButton.setShortcut('Ctrl+I')
        self.findButton = QPushButton(self)
        self.findButton.setFlat(True)
        self.findButton.setIcon(Icons.find)
        self.findButton.setShortcut("Ctrl+F")
        self.findButton.clicked.connect(self.findBarShow)
        '''
        self.zoominButton = QPushButton(self)
        self.zoominButton.setFlat(True)
        self.zoominButton.setIcon(Icons.zoomplus)
        self.zoominButton.clicked.connect(self.zoomin)
        self.zoomoutButton = QPushButton(self)
        self.zoomoutButton.setFlat(True)
        self.zoomoutButton.setIcon(Icons.zoomminus)
        self.zoomoutButton.clicked.connect(self.zoomout)
        '''

        '''Status Text,Line Text, Progress Bar and Stop Button'''
        self.statusText = QLabel("Writable")
        #self.statusText.setAlignment(Qt.AlignCenter)
        self.statusText.setFixedWidth(200)
        self.lineText = QLabel("")
        self.lineText.setFixedWidth(50)
        
        self.progressbar = QProgressBar()
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)
        self.stopButton = QPushButton(self)
        self.stopButton.setFlat(True)
        self.stopButton.setIcon(Icons.stop)
        self.stopButton.clicked.connect(self.forceStop)
        self.progressbar.hide()
        self.stopButton.hide()
        self.temp = False
        self.progress = False
        self.counter = 0
        
        '''Adding all widgets to Status Bar'''
        self.statusbar.addWidget(self.aboutButton)
        self.statusbar.addWidget(self.expButton)
        self.statusbar.addWidget(self.cmdButton)
        self.statusbar.addWidget(self.imgButton)
        self.statusbar.addWidget(self.findButton)
        #self.statusbar.addWidget(QWidget(self))
        #self.statusbar.addWidget(self.zoominButton)
        #self.statusbar.addWidget(self.zoomoutButton)
        self.statusbar.addWidget(self.statusText)
        self.statusbar.addWidget(self.lineText)
        self.statusbar.addWidget(self.progressbar)
        self.statusbar.addWidget(self.stopButton)
        #self.statusbar.setFixedHeight(18)
        
        ''''Initializing Coloring Style'''
        self.initEditorStyle()
        self.initStyleSheet()
        '''Adding Cental Widget and Status Bar'''
        self.setCentralWidget(self.centralwidget)
        self.setStatusBar(self.statusbar)
        self.textEdit.setReadOnly(True)
        
        
    def initStyleSheet(self):
        import stylesheet
        self.setStyleSheet(stylesheet.mainstyl)
        self.tabWidget.tabBar().setStyleSheet(stylesheet.stletabb)
        self.explorerTabWidget.tabBar().setStyleSheet(stylesheet.stletabb)
        self.outputTabWidget.tabBar().setStyleSheet(stylesheet.stletabb)
        self.popWidget.setStyleSheet(stylesheet.popbg)
        self.popWidget.hide()
        
        
        ''' This is for changing the palette/window colors to Theme '''
    def initEditorStyle(self):
        pass
        #editStyle = config.readStyle()
        #print editStyle
        #pal = QPalette(self.explorerTabWidget.palette())
        #print pal.color(QPalette.Base).name()
        #print pal.color(QPalette.Window).name()
        #pal.setColor(QPalette.Base,self.colorStyle.paper)
        #pal.setColor(QPalette.Text,self.colorStyle.color)
        #self.explorerTabWidget.setPalette(pal)
        #self.outputTabWidget.setPalette(pal)
         
    ''' This is only for testing dont know if it works for builds '''    
    def changeStyleSheet(self):
        ''' Dynamically load the changed stylesheet.py and load the modules and change 
            the style at runtime saves countless deploys '''
        import imp
        foo = imp.load_source('stletabb', workDir+"/stylesheet.py")
        #print foo.stletabb
        #self.setStyleSheet(stylesheet.mainstyl)
        self.tabWidget.tabBar().setStyleSheet(foo.stletabb)
        self.popWidget.setStyleSheet(foo.popbg)
        if(self.popWidget.isHidden()):
            self.popWidget.showPopup()
    
    def build_project(self):
        #current_file = self.files[self.tabWidget.currentIndex()]
        prj = self.treeWidget.getProject()
        if(prj != None):
            self.treeWidget.build(prj)
            
    def run_project(self):
        #current_file = self.files[self.tabWidget.currentIndex()]
        prj = self.treeWidget.getProject()#current_file)
        if(prj != None):
            self.treeWidget.run(prj)
            
    def forceStop(self):
        self.ant.kill()
        self.progressStop()
        
    def kill(self):
        self.deleteLater()
        
#-----------------------------------------------------------------------------------#
#   Menu Actions Functions                                                          #
#-----------------------------------------------------------------------------------#
    def run(self):
        if(config.mode() == 0):
            self.sq.run()
        elif(config.mode() == 1):
            self.adb.run()
        elif(config.mode() == 2):
            self.ios.run()
        elif(config.mode() == 3):
            self.c.run()
            
    def setMode(self, action):
        if(action.text() == "Squ"):
            config.setMode(0)
            self.toolBar.action_Build.setEnabled(False)
            self.toolBar.action_Run.setEnabled(False)
        elif(action.text() == "Emo"):
            config.setMode(1)
            self.toolBar.action_Build.setEnabled(True)
            self.toolBar.action_Run.setEnabled(True)
        elif(action.text() == "Android"):
            config.setMode(2)
            self.toolBar.action_Build.setEnabled(True)
            self.toolBar.action_Run.setEnabled(True)
        elif(action.text() == "ios"):
            config.setMode(3)
            self.toolBar.action_Build.setEnabled(False)
            self.toolBar.action_Run.setEnabled(False)
            
    def openCommand(self):
        text, ok = QInputDialog.getText(self, 'Run Command', 'Command:')
        cmd = str(text)
        if ok and cmd != "":
            import subprocess
            subprocess.Popen(cmd)
     
    def about(self):
        form = DialogAbout(self)
        
    def todo(self):
        form = DialogTodo(self)
        form.show()

    def help(self):
        QMessageBox.about(self,"Help","This is about all The Help that i can Give you now")
        
    def full(self):
        if not self.isFull:
            self.setWindowState(Qt.WindowFullScreen)
            self.isFull = True
        else:
            self.setWindowState(Qt.WindowMaximized)
            self.isFull = False
            
    def android(self):
        form = DialogAndroid(self)
        form.show()
    
    def antt(self):
        form = DialogAnt(self)
        form.show()
        
    def squirrel(self):
        form = DialogSquirrel(self)
        form.show()
        
    def findBarShow(self):
        if(self.findLayoutWidget.isHidden()):
            self.findLayoutWidget.show()
        else:
            self.findLayoutWidget.hide()
            
    def exp(self):
        if(self.explorerTabWidget.isHidden()):
            self.explorerTabWidget.show()
        else:
            self.explorerTabWidget.hide()
    
    def cmd(self):
        if(self.outputTabWidget.isHidden()):
            self.outputTabWidget.show()
        else:
            self.outputTabWidget.hide()
            
    def editor(self):
        if(self.editorLayoutWidget.isHidden()):
            self.editorLayoutWidget.show()
            self.levelLayoutWidget.hide()
            self.designerLayoutWidget.hide()
            
    def design(self):
        if(self.designerLayoutWidget.isHidden()):
            self.designerLayoutWidget.show()
            self.editorLayoutWidget.hide()
            self.levelLayoutWidget.hide()
        else:
            self.designerLayoutWidget.hide()
            self.editorLayoutWidget.show()
            
    def level(self):
        if(self.levelLayoutWidget.isHidden()):
            self.levelLayoutWidget.show()
            self.editorLayoutWidget.hide()
            self.designerLayoutWidget.hide()
        else:
            self.levelLayoutWidget.hide()
            self.editorLayoutWidget.show()
            
    def closeDesigner(self,no):
        pass
        '''
        if(no == self.tiler.closeIndex()):
            if(self.tiler.isHidden()):
                self.tiler.show()
            else:
                self.tiler.setCurrentIndex(1)
                self.tiler.hide()
        '''
     
    '''The current Changed idx of outputTabWidget is passed to this a param'''   
    def closeConsole(self,no = 2):
        if(no == 2):
            if(self.outputTabWidget.isHidden()):
                self.outputTabWidget.show()
            else:
                self.outputTabWidget.setCurrentIndex(1)
                self.outputTabWidget.hide()
                
    def popOutput(self):
        if(self.outputTabWidget.isHidden()):
            self.outputTabWidget.show()
        self.outputTabWidget.setCurrentIndex(1)
    
    def popError(self):
        if(self.outputTabWidget.isHidden()):
            self.outputTabWidget.show()
        self.outputTabWidget.setCurrentIndex(0)
        
    '''The current Changed idx of explorerTabWidget is passed to this a param'''
    def closeExplorer(self,no = 2):
        if(no == 2):
            if(self.explorerTabWidget.isHidden()):
                self.explorerTabWidget.show()
            else:
                self.explorerTabWidget.setCurrentIndex(0)
                self.explorerTabWidget.hide()
        elif(no == 1):
            self.fileChanged(no)
                
    ''' This is to refresh the outline widget'''
    def fileChanged(self,no):
        if(self.explorerTabWidget.currentIndex() == 1):
            edt = self.tabWidget.widget(self.tabWidget.currentIndex())
            source = edt.text()
            self.outlineWidget.parseText(source)
           
    def statusSaving(self):
        self.statusText.setText("Saving")   
    def statusParsing(self):
        self.statusText.setText("Parsing")   
    def statusWriting(self):
        self.statusText.setText("Writable")  
    def statusRunning(self):
        self.statusText.setText("Running")   
    def statusStopping(self):
        self.statusText.setText("Stopping")
    def statusCommand(self):
        self.statusText.setText("Command")
    def statusBuilding(self):
        self.statusText.setText("Building")
    def statusInstalling(self):
        self.statusText.setText("Installing")
    def statusCleaning(self):
        self.statusText.setText("Cleaning")
    def statusCreating(self):
        self.statusText.setText("Creating")
                
    def progressStart(self):
        self.progress == True
        self.temp == True
        if(self.progressbar.isHidden()):
            self.progressbar.show()
        if(self.stopButton.isHidden()):
            self.stopButton.show()
        self.progressbar.setValue(1)
        
    def progressStop(self):
        self.progress == False
        self.temp == False
        self.progressbar.setValue(100)
        if not(self.progressbar.isHidden()):
            self.progressbar.hide()
        if not(self.stopButton.isHidden()):
            self.stopButton.hide()
              
    def progressUpdate(self):
        if(self.progress):
            if(self.temp):
                self.counter += 1
                self.progressbar.setValue(self.counter)
                if(self.counter == 100):
                    self.temp = False
            else:
                self.counter -= 1
                self.progressbar.setValue(self.counter)
                if(self.counter == 0):
                    self.temp = True
            
                
#-----------------------------------------------------------------------------------#
#   Editor Functions                                                                #
#-----------------------------------------------------------------------------------#   
    '''Search and Replace Functions'''  
    def findCurrentText(self):
        edt = self.tabWidget.widget(self.tabWidget.currentIndex())
        edt.findText(self.lineEdit.text(),self.regex.isChecked(),self.caseSensitive.isChecked(),self.wholeWord.isChecked(),self.backward.isChecked())
    def replaceCurrentText(self):
        edt = self.tabWidget.widget(self.tabWidget.currentIndex())
        edt.replaceText(self.lineEdit_2.text()) 
    def replaceFindText(self):
        edt = self.tabWidget.widget(self.tabWidget.currentIndex())
        edt.replaceText(self.lineEdit_2.text())
        self.findCurrentText()      
    def replaceAllText(self):
        edt = self.tabWidget.widget(self.tabWidget.currentIndex())
        while(edt.findText(self.lineEdit.text(),self.regex.isChecked(),self.caseSensitive.isChecked(),self.wholeWord.isChecked(),self.backward.isChecked())):
            edt.replaceText(self.lineEdit_2.text())      
    def errorLine(self,error):
        index = self.tabWidget.currentIndex()
        edt = self.tabWidget.widget(index)
        '''To prevent File item double clicking'''
        if(error.isFile() == False):
            edt.setLine(error.line)
            
    '''Font Functions'''       
    def zoomin(self):
        pass
        #for i in range(len(self.files)):
        #    self.tabWidget.widget(i).zoomin()
    def zoomout(self):
        pass
        #for i in range(len(self.files)):
        #    self.tabWidget.widget(i).zoomout()
            
    ''' Must implement Lexer '''
    def setLexer(self, action):
        pass
        #print action.text()
    
    def setApi(self, action):
        #print action.text()
        for i in range(len(self.files)): #not QString
            self.tabWidget.widget(i).setApi(str(action.text()))
    
    def setFont(self,font):
        config.setFontName(str(font.family()))
        for i in range(len(self.files)):
            self.tabWidget.widget(i).setNewFont(font)
            
    def setFontSize(self,idx):
        fontSize = idx+1
        config.setFontSize(fontSize)
        for i in range(len(self.files)):
            self.tabWidget.widget(i).setFontSize() 
            
    def gotoLine(self,item):
        edt = self.tabWidget.widget(self.tabWidget.currentIndex())
        edt.setLine(item.line)
        
    def updateLine(self,no,col):
        self.lineText.setText(str(no)+" : "+str(col))
            
    def setMargin(self):
        mar = config.margin()
        if(mar == 0): 
            config.setMargin(1)
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setMargin(1)
        else:
            config.setMargin(0)
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setMargin(0)
                
    ''' Toggle '''
    def setIndent(self):
        indent = config.indent()
        if(indent == 0): 
            config.setIndent(1)
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setIndent(1)
        else:
            config.setIndent(0)
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setIndent(0)
    ''' Toggle '''         
    def setWhiteSpace(self):
        white = config.whiteSpace()
        if(white == 0): 
            config.setWhiteSpace(1)
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setWhitespaceVisibility(True)
        else:
            config.setWhiteSpace(0)
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setWhitespaceVisibility(False)
    
    ''' Toggle '''         
    def setEndLine(self):
        for i in range(len(self.files)):
            edt = self.tabWidget.widget(i)
            edt.setEolVisibility(not edt.eolVisibility())
                
    def setEncoding(self, action):
        if(action.text() == "Ascii"):
            config.setAscii()
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setUtf8(False)
        elif(action.text() == "Unicode"):
            config.setUnicode()
            for i in range(len(self.files)):
                self.tabWidget.widget(i).setUtf8(True)
        
    def setThreshold(self,val):
        config.setThresh(val)
        for i in range(len(self.files)):
            #print i
            self.tabWidget.widget(i).setThreshold(val)
    def setTabWidth(self,val):
        config.setTabWidth(val)
        for i in range(len(self.files)):
            #print i
            self.tabWidget.widget(i).setTabWidth(val)
    '''style Functions'''         
#-----------------------------------------------------------------------------------#
#   Command Functions                                                               #
#-----------------------------------------------------------------------------------#   
    def getFile(self):
        self.browsedialog = DialogBrowse(self)
        self.browsedialog.tree.itemDoubleClicked.connect(self.getName)
        self.browsedialog.show()
            
    def getName(self,item):
        if(item.isFile()):
                self.browsedialog.accept()
                fname = item.getPath()
                if not (fname == ""):
                    index = self.combo2.currentIndex()
                    text = str(self.combo2.itemText(index))+" "+fname
                    self.combo2.setItemText(index,text)
                    self.paramList.pop(index)
                    self.paramList.insert(index,text)
                    config.setParam(self.paramList)
                 
    def addCmd(self,index):
        text, ok = QInputDialog.getText(self, 'Add Command', 'Command:')
        if(ok):
            if(str(text) != ''):
                cmd = str(text).upper()
                self.cmdList.append(cmd)
                #print self.cmdList
                self.combo.addItem(cmd)
                config.setCmd(self.cmdList)
                config.setParam(self.paramList)
                
    def delCmd(self):
        index = self.combo.currentIndex()
        self.combo.removeItem(index)
        self.cmdList.pop(index)
        #print self.cmdList
        config.setCmd(self.cmdList)
        
    def addParam(self,index):
        text, ok = QInputDialog.getText(self, 'Add Parameters', 'Params:')
        if(ok):
            if(str(text) != ''):
                param = str(text)
                self.paramList.append(param)
                self.combo2.addItem(param)
                config.setParam(self.paramList)
                
    def delParam(self):
        index = self.combo2.currentIndex()
        self.combo2.removeItem(index)
        self.paramList.pop(index)
        config.setParam(self.paramList)
        
    def checkHasValue(self,list):
        if(list != None and len(list) != 0):
            return True
        else:
            return False
Exemple #2
0
class TabDownloads(QWidget):
    instance = None

    def __init__(self, search, parent=None):
        QWidget.__init__(self, parent)
        # Load de l'UI
        PyQt4.uic.loadUi('ui/downloads.ui', self)
        # Ajout de la progressBar
        self.progressBar = QProgressBar()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(100)
        self.progressBar.hide()
        self.HLayout = QBoxLayout(QBoxLayout.LeftToRight)
        self.HLayout.addWidget(self.progress_label)
        self.HLayout.addWidget(self.progressBar)
        self.formLayout_3.addRow(self.HLayout)
        # Vars 
        TabDownloads.instance = self
        self.downloads        = Downloads()
        self.pos              = None
        self.download_looked  = None
        # Affichage custom
        #self.downloads_table.setStyleSheet(\
        #        "QTableView::item{ \
        #         border-right-style:solid; \
        #         border-width:0.5; \
        #         border-color: #9B9B9B; \
        #         }")
        # On autorise la creation de menu contextuel
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        # Signaux
        self.customContextMenuRequested.connect(self.contextMenu)
        self.downloads_table.itemClicked.connect(self.show_info_download)
        # Init
        self.load_downloads()
        # On remove les finis et en erreur si Config.clean_dl_list = 1
        if Configuration.clean_dl_list == 1:
            self.clean_list_Action()
        #########################################################
        # On désactive les boutons qui sont pas encore implantés
        self.button_stop_all.setEnabled(False)        
        self.button_resume_all.setEnabled(False)
        #########################################################

    def load_downloads(self):
        import xml.sax
        parser = xml.sax.make_parser()
        parser.setContentHandler(AnalyseDownloads(self.add_downloads))
        try:
            for line in open(os.path.expanduser("~") + '/.pyrex/downloads.xml'):
                parser.feed(line)
            self.downloads.save()
        except:
            pass

    def add_download(self, download):
        # Avant de filtrer on écrit le download
        #self.downloads.append(download) #TODO : pour quand on pourra resume, décommenter la ligne et ramener le save ici
                
        if download.state == 4 or download.progress == 0:
            rows = self.downloads_table.rowCount()
            self.downloads_table.insertRow(rows)
            self.downloads_table.setItem(rows, 0, MyQTableWidgetItem(download.file_share.name, download))
            self.downloads_table.setItem(rows, 1, QTableWidgetItem(download.get_progress()))
            self.downloads_table.setItem(rows, 2, QTableWidgetItem(download.state_str))
            self.downloads_table.setItem(rows, 3, QTableWidgetItem("0 ko/s"))
            self.downloads_table.setItem(rows, 5, QTableWidgetItem(download.date.strftime('%d/%m/%y')))
            self.downloads.append(download)
                    
        # TODO : à modifier probablement quand on aura le resume pour les downloads
        if download.state != 4 and download.progress == 0:
            # Signaux
            download.progressModified.connect(self.update_progress)
            download.stateChanged.connect(self.update_state)
            download.downloadFinished.connect(self.download_finished)
            download.speedModified.connect(self.update_speed)
        
        # On save
        self.downloads.save()
        
    def add_downloads(self, downloads):
        for download in downloads:
          self.add_download(download)
        
    def update_progress(self, download):
        item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0]
        row = self.downloads_table.row(item)
        self.downloads_table.item(row, 1).setText(download.get_progress())
        # On update la barre de progression si on est en train de regarder un download
        if self.download_looked == download:
            self.progressBar.setValue(int(download.progress))

    def update_speed(self, download):
        item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0]
        row = self.downloads_table.row(item)
        self.downloads_table.item(row, 3).setText(convert_speed_str(download.speed))
        
    def update_state(self, download):
        item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0]
        row = self.downloads_table.row(item)
        self.downloads_table.item(row, 2).setText(download.state_str)
        # On save
        self.downloads.save()
        
    def download_finished(self, download):
        if download.read_bytes == download.file_share.size:
            item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0]
            row = self.downloads_table.row(item)
            self.downloads_table.item(row, 2).setText("Finished!")
            self.downloads_table.item(row, 3).setText("")
            # On save
            self.downloads.save()
        else:
            print "Erreur dans le téléchargement"
            item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0]
            row = self.downloads_table.row(item)
            self.downloads_table.item(row, 2).setText("Error : invalid size :(")
            self.downloads_table.item(row, 3).setText("")
            # On save
            self.downloads.save()
            
    def contextMenu(self, pos):
        self.pos = pos
        menu = QMenu()
        # Actions 
        forceAction         = menu.addAction("Forcer la reprise")
        continueAction      = menu.addAction("Reprise")
        pauseAction         = menu.addAction("Pause")
        openAction          = menu.addAction("Ouvrir")
        abortAction         = menu.addAction("Annuler")
        supprListeAction    = menu.addAction("Supprimer de la liste")
        supprDiskAction     = menu.addAction("Supprimer de la liste et du disque")
        copyAction          = menu.addAction("Copier l'URL")
        searchAction        = menu.addAction("Rechercher des fichiers similaires")
        # On désactive les actions s'il n'y a pas de downloads
        if self.downloads == [] or self.downloads_table.currentRow() < 0:
            forceAction.setEnabled(False)
            continueAction.setEnabled(False)
            pauseAction.setEnabled(False)
            openAction.setEnabled(False)
            abortAction.setEnabled(False)
            supprListeAction.setEnabled(False)
            supprDiskAction.setEnabled(False)
            copyAction.setEnabled(False)
            searchAction.setEnabled(False)
        #########################################################
        # On désactive les boutons qui sont pas encore implantés
        forceAction.setEnabled(False)
        #continueAction.setEnabled(False)
        #pauseAction.setEnabled(False)        
        searchAction.setEnabled(False)        
        #########################################################
        # Signaux
        self.connect(forceAction, SIGNAL('triggered()'), self.force_Action)
        self.connect(continueAction, SIGNAL('triggered()'), self.continue_Action)
        self.connect(pauseAction, SIGNAL('triggered()'), self.pause_Action)
        self.connect(openAction, SIGNAL('triggered()'), self.open_Action)
        self.connect(abortAction, SIGNAL('triggered()'), self.abort_Action)
        self.connect(supprListeAction, SIGNAL('triggered()'), self.suppr_liste_Action)
        self.connect(supprDiskAction, SIGNAL('triggered()'), self.suppr_disk_Action)
        self.connect(copyAction, SIGNAL('triggered()'), self.copy_Action)
        self.connect(searchAction, SIGNAL('triggered()'), self.search_Action)
        # On affiche le menu
        menu.exec_(self.mapToGlobal(pos))
      
    def getDownloads(self):
        rows = self.downloads_table.selectionModel().selectedRows()
        return [self.downloads_table.item(row.row(), 0).download for row in rows]
          
    def force_Action(self):
        print "TODO"
        
    def continue_Action(self):
        for download in self.getDownloads():
            print "Resuming download"
            download.resume()
        self.display_resume_pause()
        
    def pause_Action(self):
        for download in self.getDownloads():
            print "Pausing download"
            download.pause()
        self.display_resume_pause()
        
    def open_Action(self):
        for download in self.getDownloads():
            open_file(download.local_path)
        
    def abort_Action(self):
        for download in self.getDownloads():
            download.stop()
        row = self.downloads_table.currentRow()
        self.downloads_table.item(row, 2).setText(u"Annulé!")
        self.downloads_table.item(row, 3).setText("")
  
    def remove_download(self, download, erase):
        download.stop()
        row = self.downloads_table.currentRow()
        # On supprime la ligne
        self.downloads_table.removeRow(row)
        # On supprime de la liste
        self.downloads.remove(download)    
        # On save
        self.downloads.save()
        if erase:
            try:
                os.remove(download.local_path)
            except OSError:
                try:
                    shutil.rmtree(download.local_path)
                except:
                    print "Erreur dans la suppression du fichier"

    def suppr_liste_Action(self):
        for download in self.getDownload():
            self.remove_download(download, False)
        
    def suppr_disk_Action(self):
        for download in self.getDownloads():
            self.remove_download(download, True)
        
    def copy_Action(self):
        pressPaper = QApplication.clipboard()
        text = '\n'.join([dl.local_path for dl in self.getDownloads()])
        pressPaper.setText(text)
        
    def search_Action(self):
        print "TODO"
        
    def show_info_download(self):
        download = self.getDownloads()[0]
        self.name_label.setText(u"Nom : {}".format(download.file_share.name))
        self.path_label.setText(u"Chemin local : {}".format(download.local_path))
        self.url_label.setText(u"URL : {}".format(download.file_share.url))
        self.size_label.setText(u"Taille : {}".format(download.file_share.str_size))   
        self.progressBar.show()     
        self.progressBar.setValue(int(download.progress))
        self.download_looked = download
        
    def clean_list_Action(self):
        remove_list = []
        for download in self.downloads:
            if download.state == 4 or download.state == 7:
                # On trouve la ligne
                item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0]
                row = self.downloads_table.row(item)
                # On la supprime
                self.downloads_table.removeRow(row)
                # On save pour après la boucle for
                remove_list.append(download)
        # On supprime de la liste
        for download in remove_list:
            self.downloads.remove(download)    
        # On save
        self.downloads.save()
                               
    def double_clicked(self, row, col):
        download = self.getDownloads()[0]
        if download:
            open_file(download.local_path)
            
    def display_resume_pause(self):
        downloads = self.getDownloads()
        pause = False
        resume = False
        if downloads:
            for download in downloads:
                if download.state == 5:
                    pause = True
                else:
                    resume = True
            self.button_pause.setEnabled(resume)
            self.button_resume.setEnabled(pause)
                    
    def clicked(self, row, col):
        self.display_resume_pause()    
        
    def resizeEvent(self, event):
        maxSize = self.downloads_table.size().width()
        # Nom Ficher : 24%
        self.downloads_table.horizontalHeader().resizeSection(0, maxSize*.24)
        # Avancement : 22%
        self.downloads_table.horizontalHeader().resizeSection(1, maxSize*.22)
        # Etat : 17%
        self.downloads_table.horizontalHeader().resizeSection(2, maxSize*.17)
        # Vitesse : 13% 
        self.downloads_table.horizontalHeader().resizeSection(3, maxSize*.13)
        # Fin : 12%
        self.downloads_table.horizontalHeader().resizeSection(4, maxSize*.12)
        event.accept()
class MainWindow(KXmlGuiWindow):

    "Class which displays the main Danbooru Client window."

    def __init__(self,  *args):

        "Initialize a new main window."

        super(MainWindow,  self).__init__(*args)
        self.cache = KPixmapCache("danbooru")
        self.preferences = preferences.Preferences()
        self.api = None
        self.__ratings = None
        self.__step = 0

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

        self.statusbar = self.statusBar()
        self.progress = QProgressBar()
        self.thumbnailarea = None
        self.tag_dock = None
        self.pool_dock = None
        self.first_fetch_widget = None

        self.progress.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        # FIXME: Hackish, but how to make it small otherwise?
        self.progress.setMinimumSize(100, 1)
        self.statusbar.addPermanentWidget(self.progress)
        self.progress.hide()

        self.setup_welcome_widget()
        self.setup_actions()

    def reload_config(self):

        """Reload configuration after a change"""

        urls = self.preferences.boards_list

        if self.first_fetch_widget is not None:
            self.first_fetch_widget.setup_urls(urls)

        if self.thumbnailarea is not None:

            max_thumbnail = self.preferences.thumbnail_no
            max_rating = self.preferences.max_allowed_rating

            self.thumbnailarea.fetchwidget.limit = max_thumbnail
            self.thumbnailarea.fetchwidget.rating = max_rating
            self.thumbnailarea.fetchwidget.update_values()

            self.thumbnailarea.connectwidget.setup_urls(urls)

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no




    def setup_welcome_widget(self):

        """Load the welcome widget at startup."""

        widget = QWidget()
        layout = QVBoxLayout()

        welcome = QLabel(parent=self)
        pix = QPixmap(KStandardDirs.locate("appdata","logo.png"))

        welcome.setPixmap(pix)
        welcome.setAlignment(Qt.AlignCenter)

        self.first_fetch_widget = connectwidget.ConnectWidget(
        self.preferences.boards_list, self)

        self.statusbar.addPermanentWidget(self.first_fetch_widget, 300)

        self.first_fetch_widget.connectionEstablished.connect(
            self.handle_connection)
        self.first_fetch_widget.rejected.connect(
            self.first_fetch_widget.hide)

        self.first_fetch_widget.hide()

        self.first_fetch_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)

        layout.addWidget(self.first_fetch_widget)
        layout.addWidget(welcome)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def setup_tooltips(self):

        """Set tooltips for the actions."""

        self.connect_action.setToolTip(i18n("Connect to a Danbooru board"))
        self.fetch_action.setToolTip(
            i18n("Fetch thumbnails from a Danbooru board")
        )
        self.batch_download_action.setToolTip(i18n("Batch download images"))

    def create_actions(self):

        """Create actions for the main window."""

        self.connect_action = KAction(KIcon("document-open-remote"),
                                 i18n("Connect"), self)
        self.fetch_action = KAction(KIcon("download"), i18n("Download"),
                                    self)
        self.clean_action = KAction(KIcon("trash-empty"),
                               i18n("Clear thumbnail cache"),
                               self)
        self.batch_download_action = KAction(KIcon("download"),
                                             i18n("Batch download"), self)
        self.pool_toggle_action = KToggleAction(KIcon("image-x-generic"),
                                            i18n("Pools"), self)
        self.tag_display_action = KDualAction(i18n("Show tags"),
                                              i18n("Hide tags"),
                                              self)
        self.tag_display_action.setIconForStates(KIcon("image-x-generic"))
        self.tag_display_action.setEnabled(False)

        # Shortcuts
        connect_default = KAction.ShortcutTypes(KAction.DefaultShortcut)
        connect_active = KAction.ShortcutTypes(KAction.ActiveShortcut)

        self.connect_action.setShortcut(KStandardShortcut.open())
        self.fetch_action.setShortcut(KStandardShortcut.find())

        self.fetch_action.setEnabled(False)
        self.batch_download_action.setEnabled(False)
        self.pool_toggle_action.setEnabled(False)

    def setup_action_collection(self):

        """Set up the action collection by adding the actions."""

        action_collection = self.actionCollection()

        # Addition to the action collection
        action_collection.addAction("connect", self.connect_action)
        action_collection.addAction("fetch", self.fetch_action)
        action_collection.addAction("clean", self.clean_action)
        action_collection.addAction("batchDownload", self.batch_download_action)
        action_collection.addAction("poolDownload", self.pool_toggle_action)
        action_collection.addAction("tagDisplay", self.tag_display_action)

        KStandardAction.quit (self.close, action_collection)
        KStandardAction.preferences(self.show_preferences,
                                    action_collection)

        action_collection.removeAction(
            action_collection.action("help_contents"))
        action_collection.actionHovered.connect(self.setup_action_tooltip)

    def setup_actions(self):

        """Set up the relevant actions, tooltips, and load the RC file."""

        self.create_actions()
        self.setup_tooltips()
        self.setup_action_collection()

        # Connect signals
        self.connect_action.triggered.connect(self.connect)
        self.fetch_action.triggered.connect(self.get_posts)
        self.clean_action.triggered.connect(self.clean_cache)
        self.batch_download_action.triggered.connect(self.batch_download)
        self.pool_toggle_action.toggled.connect(self.pool_toggle)
        self.tag_display_action.activeChanged.connect(self.tag_display)

        window_options = self.StandardWindowOption(self.ToolBar| self.Keys |
                                                   self.Create | self.Save |
                                                   self.StatusBar)

        setupGUI_args = [
            QSize(500, 400), self.StandardWindowOption(window_options)
        ]

        #Check first in standard locations for danbooruui.rc

        rc_file = KStandardDirs.locate("appdata", "danbooruui.rc")

        if rc_file.isEmpty():
            setupGUI_args.append(os.path.join(sys.path [0],
                                              "danbooruui.rc"))
        else:
            setupGUI_args.append(rc_file)

        self.setupGUI(*setupGUI_args)

    def setup_action_tooltip(self, action):

        "Show statusbar help when actions are hovered."

        if action.isEnabled():
            self.statusBar().showMessage(action.toolTip(), 2000)

    def setup_connections(self):

        """Set up connections for post and tag retrieval."""

        if self.api is None:
            return

        self.api.postRetrieved.connect(self.update_progress)
        self.api.postDownloadFinished.connect(self.download_finished)
        self.api.tagRetrieved.connect(self.tag_dock.widget().add_tags)
        self.tag_dock.widget().itemDoubleClicked.connect(
            self.fetch_tagged_items)

    def show_preferences(self):

        "Show the preferences dialog."

        if KConfigDialog.showDialog("Preferences dialog"):
            return
        else:
            dialog = preferences.PreferencesDialog(self, "Preferences dialog",
                                                   self.preferences)
            dialog.show()
            dialog.settingsChanged.connect(self.reload_config)

    def connect(self, ok):

        "Connect to a Danbooru board."

        if self.thumbnailarea is None:
            self.first_fetch_widget.show()
        else:
            self.thumbnailarea.connectwidget.show()


    def restore(self):

        self.statusbar.removeWidget(self.connect_widget)

    def handle_connection(self, connection):

        self.api = None
        self.api = connection
        self.api.cache = self.cache

        if self.pool_dock is not None:
            self.pool_dock.hide()
            self.pool_dock.widget().clear()
            self.pool_toggle_action.setChecked(False)

        if self.thumbnailarea is not None:
            #TODO: Investigate usability
            self.clear(clear_pool=True)
            self.thumbnailarea.clear()
            self.thumbnailarea.api_data = self.api
            self.setup_connections()

        else:
            self.first_fetch_widget.connectionEstablished.disconnect()
            self.first_fetch_widget.rejected.disconnect()
            self.statusbar.removeWidget(self.first_fetch_widget)
            self.setup_area()

        self.api.cache = self.cache

        self.statusBar().showMessage(i18n("Connected to %s" % self.api.url),
                                     3000)
        self.fetch_action.setEnabled(True)

        # Set up pool widget

        pool_widget = poolwidget.DanbooruPoolWidget(self.api)
        self.pool_dock = QDockWidget("Pools", self)
        self.pool_dock.setObjectName("PoolDock")
        self.pool_dock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.pool_dock.setWidget(pool_widget)
        #self.pool_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.pool_dock)
        self.pool_dock.widget().poolDownloadRequested.connect(
            self.pool_prepare)
        self.pool_dock.hide()

        self.pool_toggle_action.setEnabled(True)
        self.clear() # Needed to show properly the stuff after connecting

        self.api.get_post_list(tags="", limit=self.thumbnailarea.post_limit,
                               rating=self.preferences.max_allowed_rating,
                               blacklist=list(self.preferences.tag_blacklist))
        self.api.get_tag_list(name="",blacklist=list(self.preferences.tag_blacklist),
                              limit=20)

    def get_posts(self, ok):

        "Get posts from the connected Danbooru board."

        if not self.api:
            return

        self.thumbnailarea.fetchwidget.show()



    def handle_fetching(self, tags, max_rating, limit):

        """Slot connected to the dataSent signal of the fetch widget.

        The widgets are set up if they don't exist, and the API is queried
        to do the actual downloading of tags and

        """

        self.clear()

        self.thumbnailarea.fetchwidget.hide()

        if self.tag_dock is not None:
            self.tag_dock.widget().clear()

        self.thumbnailarea.post_limit = limit
        blacklist= list(self.preferences.tag_blacklist)
        self.api.get_post_list(tags=tags, limit=limit,
                               rating=max_rating,
                               blacklist=blacklist)

        tags = [item for item in tags if item]

        if not tags:
            # No related tags, fetch the most recent 20
            tags = ""
            self.api.get_tag_list(name=tags,blacklist=blacklist,
                                  limit=20)
        else:
            self.api.get_related_tags(tags=tags, blacklist=blacklist)

    def fetch_tagged_items(self, item):

        """Fetch items found in the tag list widget."""

        tag_name = unicode(item.text())
        self.clear()

        blacklist = self.preferences.tag_blacklist
        limit = self.preferences.thumbnail_no
        rating = self.preferences.max_allowed_rating

        self.api.get_post_list(page=1, tags=[tag_name],
                                blacklist=blacklist,
                                limit=limit,
                                rating=rating)
        self.api.get_related_tags(tags=[tag_name], blacklist=blacklist)

    def pool_toggle(self, checked):

        "Toggle the presence/absence of the pool dock."

        if not self.api:
            return

        if not checked:
            self.pool_dock.hide()
        else:
            self.pool_dock.show()

    def pool_prepare(self, pool_id):

        """Prepare the central area for pool image loading."""

        if self.thumbnailarea is None:
            self.setup_area()
        else:
            self.clear(clear_pool=False)

        self.api.get_pool(pool_id, blacklist=self.preferences.tag_blacklist,
                          rating=self.preferences.max_allowed_rating)

    def batch_download(self, ok):

        "Download images in batch."

        selected_items = self.thumbnailarea.selected_images()

        if not selected_items:
            return

        start_url = KUrl("kfiledialog:///danbooru")
        caption = i18n("Select a directory to save the images to")
        directory = KFileDialog.getExistingDirectoryUrl(start_url, self,
                                                        caption)

        if directory.isEmpty():
            return

        for item in selected_items:

            file_url = item.url_label.url()
            tags = item.data.tags

            # Make a local copy to append paths as addPath works in-place
            destination = KUrl(directory)

            file_name = KUrl(file_url).fileName()
            destination.addPath(file_name)

            job = KIO.file_copy(KUrl(file_url), destination, -1)
            job.setProperty("tags", QVariant(tags))
            job.result.connect(self.batch_download_slot)

    def setup_area(self):

        "Set up the central widget to display thumbnails."

        self.thumbnailarea = thumbnailarea.DanbooruTabWidget(self.api,
            self.preferences, self.preferences.thumbnail_no, self)

        self.setCentralWidget(self.thumbnailarea)

        self.thumbnailarea.connectwidget.connectionEstablished.connect(
                    self.handle_connection, type=Qt.UniqueConnection)
        self.thumbnailarea.connectwidget.rejected.connect(
            self.thumbnailarea.connectwidget.hide, type=Qt.UniqueConnection)

        self.thumbnailarea.fetchwidget.dataSent.connect(
            self.handle_fetching, type=Qt.UniqueConnection)
        self.thumbnailarea.fetchwidget.rejected.connect(
            self.thumbnailarea.fetchwidget.hide, type=Qt.UniqueConnection)

        # Set up tag widget

        blacklist = self.preferences.tag_blacklist
        tag_widget = tagwidget.DanbooruTagWidget(blacklist, self)
        self.tag_display_action.setActive(True)
        self.tag_display_action.setEnabled(True)
        self.tag_dock = QDockWidget("Similar tags", self)
        self.tag_dock.setObjectName("TagDock")
        self.tag_dock.setAllowedAreas(Qt.RightDockWidgetArea)
        self.tag_dock.setWidget(tag_widget)
        #self.tag_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, self.tag_dock)
        self.tag_dock.hide()

        # Container signal-slot connections

        self.setup_connections()

    def download_finished(self):

        """Slot called when all the data has been completed. Clears the progress
        bar and resets it to 0."""

        if not self.batch_download_action.isEnabled():
            self.batch_download_action.setEnabled(True)

        self.__step = 0
        self.progress.hide()

    def update_progress(self):

        "Update the progress bar."

        if not self.progress.isVisible():
            self.progress.show()

        self.__step += 1
        self.progress.setValue(self.__step)

    def clear(self, clear_pool=True):

        "Clear the central widget."

        if self.thumbnailarea is None:
            return

        self.thumbnailarea.clear()
        self.tag_dock.widget().clear()
        if clear_pool:
            self.pool_dock.widget().clear()
        self.batch_download_action.setEnabled(False)

    def clean_cache(self):

        "Purge the thumbnail cache."

        self.cache.discard()
        self.statusBar().showMessage(i18n("Thumbnail cache cleared."))

    def batch_download_slot(self, job):

        """Slot called when doing batch download, for each file retrieved.

        If Nepomuk tagging is enabled, each file is tagged using the item's
        respective tags.

        """

        if job.error():
            job.ui().showErrorMessage()
        else:
            if self.preferences.nepomuk_enabled:
                tags = job.property("tags").toPyObject()
                #danbooru2nepomuk.tag_danbooru_item(job.destUrl().path(),
                #                                   tags)

    def tag_display(self, state):

        """Display or hide the tag dock."""

        if self.tag_dock is None:
            self.tag_display_action.setActive(False)
            return

        if state:
            self.tag_dock.show()
        else:
            self.tag_dock.hide()
class MainWindow(KXmlGuiWindow):

    "Class which displays the main Danbooru Client window."

    def __init__(self, *args):

        "Initialize a new main window."

        super(MainWindow, self).__init__(*args)
        self.cache = KPixmapCache("danbooru")
        self.preferences = preferences.Preferences()
        self.api = None
        self.__ratings = None
        self.__step = 0

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

        self.statusbar = self.statusBar()
        self.progress = QProgressBar()
        self.thumbnailarea = None
        self.tag_dock = None
        self.pool_dock = None
        self.first_fetch_widget = None

        self.progress.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        # FIXME: Hackish, but how to make it small otherwise?
        self.progress.setMinimumSize(100, 1)
        self.statusbar.addPermanentWidget(self.progress)
        self.progress.hide()

        self.setup_welcome_widget()
        self.setup_actions()

    def reload_config(self):
        """Reload configuration after a change"""

        urls = self.preferences.boards_list

        if self.first_fetch_widget is not None:
            self.first_fetch_widget.setup_urls(urls)

        if self.thumbnailarea is not None:

            max_thumbnail = self.preferences.thumbnail_no
            max_rating = self.preferences.max_allowed_rating

            self.thumbnailarea.fetchwidget.limit = max_thumbnail
            self.thumbnailarea.fetchwidget.rating = max_rating
            self.thumbnailarea.fetchwidget.update_values()

            self.thumbnailarea.connectwidget.setup_urls(urls)

        self.url_list = self.preferences.boards_list
        self.max_retrieve = self.preferences.thumbnail_no

    def setup_welcome_widget(self):
        """Load the welcome widget at startup."""

        widget = QWidget()
        layout = QVBoxLayout()

        welcome = QLabel(parent=self)
        pix = QPixmap(KStandardDirs.locate("appdata", "logo.png"))

        welcome.setPixmap(pix)
        welcome.setAlignment(Qt.AlignCenter)

        self.first_fetch_widget = connectwidget.ConnectWidget(
            self.preferences.boards_list, self)

        self.statusbar.addPermanentWidget(self.first_fetch_widget, 300)

        self.first_fetch_widget.connectionEstablished.connect(
            self.handle_connection)
        self.first_fetch_widget.rejected.connect(self.first_fetch_widget.hide)

        self.first_fetch_widget.hide()

        self.first_fetch_widget.setSizePolicy(QSizePolicy.Preferred,
                                              QSizePolicy.Fixed)

        layout.addWidget(self.first_fetch_widget)
        layout.addWidget(welcome)
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def setup_tooltips(self):
        """Set tooltips for the actions."""

        self.connect_action.setToolTip(i18n("Connect to a Danbooru board"))
        self.fetch_action.setToolTip(
            i18n("Fetch thumbnails from a Danbooru board"))
        self.batch_download_action.setToolTip(i18n("Batch download images"))

    def create_actions(self):
        """Create actions for the main window."""

        self.connect_action = KAction(KIcon("document-open-remote"),
                                      i18n("Connect"), self)
        self.fetch_action = KAction(KIcon("download"), i18n("Download"), self)
        self.clean_action = KAction(KIcon("trash-empty"),
                                    i18n("Clear thumbnail cache"), self)
        self.batch_download_action = KAction(KIcon("download"),
                                             i18n("Batch download"), self)
        self.pool_toggle_action = KToggleAction(KIcon("image-x-generic"),
                                                i18n("Pools"), self)
        self.tag_display_action = KDualAction(i18n("Show tags"),
                                              i18n("Hide tags"), self)
        self.tag_display_action.setIconForStates(KIcon("image-x-generic"))
        self.tag_display_action.setEnabled(False)

        # Shortcuts
        connect_default = KAction.ShortcutTypes(KAction.DefaultShortcut)
        connect_active = KAction.ShortcutTypes(KAction.ActiveShortcut)

        self.connect_action.setShortcut(KStandardShortcut.open())
        self.fetch_action.setShortcut(KStandardShortcut.find())

        self.fetch_action.setEnabled(False)
        self.batch_download_action.setEnabled(False)
        self.pool_toggle_action.setEnabled(False)

    def setup_action_collection(self):
        """Set up the action collection by adding the actions."""

        action_collection = self.actionCollection()

        # Addition to the action collection
        action_collection.addAction("connect", self.connect_action)
        action_collection.addAction("fetch", self.fetch_action)
        action_collection.addAction("clean", self.clean_action)
        action_collection.addAction("batchDownload",
                                    self.batch_download_action)
        action_collection.addAction("poolDownload", self.pool_toggle_action)
        action_collection.addAction("tagDisplay", self.tag_display_action)

        KStandardAction.quit(self.close, action_collection)
        KStandardAction.preferences(self.show_preferences, action_collection)

        action_collection.removeAction(
            action_collection.action("help_contents"))
        action_collection.actionHovered.connect(self.setup_action_tooltip)

    def setup_actions(self):
        """Set up the relevant actions, tooltips, and load the RC file."""

        self.create_actions()
        self.setup_tooltips()
        self.setup_action_collection()

        # Connect signals
        self.connect_action.triggered.connect(self.connect)
        self.fetch_action.triggered.connect(self.get_posts)
        self.clean_action.triggered.connect(self.clean_cache)
        self.batch_download_action.triggered.connect(self.batch_download)
        self.pool_toggle_action.toggled.connect(self.pool_toggle)
        self.tag_display_action.activeChanged.connect(self.tag_display)

        window_options = self.StandardWindowOption(self.ToolBar | self.Keys
                                                   | self.Create | self.Save
                                                   | self.StatusBar)

        setupGUI_args = [
            QSize(500, 400),
            self.StandardWindowOption(window_options)
        ]

        #Check first in standard locations for danbooruui.rc

        rc_file = KStandardDirs.locate("appdata", "danbooruui.rc")

        if rc_file.isEmpty():
            setupGUI_args.append(os.path.join(sys.path[0], "danbooruui.rc"))
        else:
            setupGUI_args.append(rc_file)

        self.setupGUI(*setupGUI_args)

    def setup_action_tooltip(self, action):

        "Show statusbar help when actions are hovered."

        if action.isEnabled():
            self.statusBar().showMessage(action.toolTip(), 2000)

    def setup_connections(self):
        """Set up connections for post and tag retrieval."""

        if self.api is None:
            return

        self.api.postRetrieved.connect(self.update_progress)
        self.api.postDownloadFinished.connect(self.download_finished)
        self.api.tagRetrieved.connect(self.tag_dock.widget().add_tags)
        self.tag_dock.widget().itemDoubleClicked.connect(
            self.fetch_tagged_items)

    def show_preferences(self):

        "Show the preferences dialog."

        if KConfigDialog.showDialog("Preferences dialog"):
            return
        else:
            dialog = preferences.PreferencesDialog(self, "Preferences dialog",
                                                   self.preferences)
            dialog.show()
            dialog.settingsChanged.connect(self.reload_config)

    def connect(self, ok):

        "Connect to a Danbooru board."

        if self.thumbnailarea is None:
            self.first_fetch_widget.show()
        else:
            self.thumbnailarea.connectwidget.show()

    def restore(self):

        self.statusbar.removeWidget(self.connect_widget)

    def handle_connection(self, connection):

        self.api = None
        self.api = connection
        self.api.cache = self.cache

        if self.pool_dock is not None:
            self.pool_dock.hide()
            self.pool_dock.widget().clear()
            self.pool_toggle_action.setChecked(False)

        if self.thumbnailarea is not None:
            #TODO: Investigate usability
            self.clear(clear_pool=True)
            self.thumbnailarea.clear()
            self.thumbnailarea.api_data = self.api
            self.setup_connections()

        else:
            self.first_fetch_widget.connectionEstablished.disconnect()
            self.first_fetch_widget.rejected.disconnect()
            self.statusbar.removeWidget(self.first_fetch_widget)
            self.setup_area()

        self.api.cache = self.cache

        self.statusBar().showMessage(i18n("Connected to %s" % self.api.url),
                                     3000)
        self.fetch_action.setEnabled(True)

        # Set up pool widget

        pool_widget = poolwidget.DanbooruPoolWidget(self.api)
        self.pool_dock = QDockWidget("Pools", self)
        self.pool_dock.setObjectName("PoolDock")
        self.pool_dock.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.pool_dock.setWidget(pool_widget)
        #self.pool_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.pool_dock)
        self.pool_dock.widget().poolDownloadRequested.connect(
            self.pool_prepare)
        self.pool_dock.hide()

        self.pool_toggle_action.setEnabled(True)
        self.clear()  # Needed to show properly the stuff after connecting

        self.api.get_post_list(tags="",
                               limit=self.thumbnailarea.post_limit,
                               rating=self.preferences.max_allowed_rating,
                               blacklist=list(self.preferences.tag_blacklist))
        self.api.get_tag_list(name="",
                              blacklist=list(self.preferences.tag_blacklist),
                              limit=20)

    def get_posts(self, ok):

        "Get posts from the connected Danbooru board."

        if not self.api:
            return

        self.thumbnailarea.fetchwidget.show()

    def handle_fetching(self, tags, max_rating, limit):
        """Slot connected to the dataSent signal of the fetch widget.

        The widgets are set up if they don't exist, and the API is queried
        to do the actual downloading of tags and

        """

        self.clear()

        self.thumbnailarea.fetchwidget.hide()

        if self.tag_dock is not None:
            self.tag_dock.widget().clear()

        self.thumbnailarea.post_limit = limit
        blacklist = list(self.preferences.tag_blacklist)
        self.api.get_post_list(tags=tags,
                               limit=limit,
                               rating=max_rating,
                               blacklist=blacklist)

        tags = [item for item in tags if item]

        if not tags:
            # No related tags, fetch the most recent 20
            tags = ""
            self.api.get_tag_list(name=tags, blacklist=blacklist, limit=20)
        else:
            self.api.get_related_tags(tags=tags, blacklist=blacklist)

    def fetch_tagged_items(self, item):
        """Fetch items found in the tag list widget."""

        tag_name = unicode(item.text())
        self.clear()

        blacklist = self.preferences.tag_blacklist
        limit = self.preferences.thumbnail_no
        rating = self.preferences.max_allowed_rating

        self.api.get_post_list(page=1,
                               tags=[tag_name],
                               blacklist=blacklist,
                               limit=limit,
                               rating=rating)
        self.api.get_related_tags(tags=[tag_name], blacklist=blacklist)

    def pool_toggle(self, checked):

        "Toggle the presence/absence of the pool dock."

        if not self.api:
            return

        if not checked:
            self.pool_dock.hide()
        else:
            self.pool_dock.show()

    def pool_prepare(self, pool_id):
        """Prepare the central area for pool image loading."""

        if self.thumbnailarea is None:
            self.setup_area()
        else:
            self.clear(clear_pool=False)

        self.api.get_pool(pool_id,
                          blacklist=self.preferences.tag_blacklist,
                          rating=self.preferences.max_allowed_rating)

    def batch_download(self, ok):

        "Download images in batch."

        selected_items = self.thumbnailarea.selected_images()

        if not selected_items:
            return

        start_url = KUrl("kfiledialog:///danbooru")
        caption = i18n("Select a directory to save the images to")
        directory = KFileDialog.getExistingDirectoryUrl(
            start_url, self, caption)

        if directory.isEmpty():
            return

        for item in selected_items:

            file_url = item.url_label.url()
            tags = item.data.tags

            # Make a local copy to append paths as addPath works in-place
            destination = KUrl(directory)

            file_name = KUrl(file_url).fileName()
            destination.addPath(file_name)

            job = KIO.file_copy(KUrl(file_url), destination, -1)
            job.setProperty("tags", QVariant(tags))
            job.result.connect(self.batch_download_slot)

    def setup_area(self):

        "Set up the central widget to display thumbnails."

        self.thumbnailarea = thumbnailarea.DanbooruTabWidget(
            self.api, self.preferences, self.preferences.thumbnail_no, self)

        self.setCentralWidget(self.thumbnailarea)

        self.thumbnailarea.connectwidget.connectionEstablished.connect(
            self.handle_connection, type=Qt.UniqueConnection)
        self.thumbnailarea.connectwidget.rejected.connect(
            self.thumbnailarea.connectwidget.hide, type=Qt.UniqueConnection)

        self.thumbnailarea.fetchwidget.dataSent.connect(
            self.handle_fetching, type=Qt.UniqueConnection)
        self.thumbnailarea.fetchwidget.rejected.connect(
            self.thumbnailarea.fetchwidget.hide, type=Qt.UniqueConnection)

        # Set up tag widget

        blacklist = self.preferences.tag_blacklist
        tag_widget = tagwidget.DanbooruTagWidget(blacklist, self)
        self.tag_display_action.setActive(True)
        self.tag_display_action.setEnabled(True)
        self.tag_dock = QDockWidget("Similar tags", self)
        self.tag_dock.setObjectName("TagDock")
        self.tag_dock.setAllowedAreas(Qt.RightDockWidgetArea)
        self.tag_dock.setWidget(tag_widget)
        #self.tag_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, self.tag_dock)
        self.tag_dock.hide()

        # Container signal-slot connections

        self.setup_connections()

    def download_finished(self):
        """Slot called when all the data has been completed. Clears the progress
        bar and resets it to 0."""

        if not self.batch_download_action.isEnabled():
            self.batch_download_action.setEnabled(True)

        self.__step = 0
        self.progress.hide()

    def update_progress(self):

        "Update the progress bar."

        if not self.progress.isVisible():
            self.progress.show()

        self.__step += 1
        self.progress.setValue(self.__step)

    def clear(self, clear_pool=True):

        "Clear the central widget."

        if self.thumbnailarea is None:
            return

        self.thumbnailarea.clear()
        self.tag_dock.widget().clear()
        if clear_pool:
            self.pool_dock.widget().clear()
        self.batch_download_action.setEnabled(False)

    def clean_cache(self):

        "Purge the thumbnail cache."

        self.cache.discard()
        self.statusBar().showMessage(i18n("Thumbnail cache cleared."))

    def batch_download_slot(self, job):
        """Slot called when doing batch download, for each file retrieved.

        If Nepomuk tagging is enabled, each file is tagged using the item's
        respective tags.

        """

        if job.error():
            job.ui().showErrorMessage()
        else:
            if self.preferences.nepomuk_enabled:
                tags = job.property("tags").toPyObject()
                #danbooru2nepomuk.tag_danbooru_item(job.destUrl().path(),
                #                                   tags)

    def tag_display(self, state):
        """Display or hide the tag dock."""

        if self.tag_dock is None:
            self.tag_display_action.setActive(False)
            return

        if state:
            self.tag_dock.show()
        else:
            self.tag_dock.hide()
Exemple #5
0
class frmReportes( QPrintPreviewDialog ):
    """
    Este es un formulario generico que muestra los reportes web generados para las 
    """
    def __init__( self, web, printer , parent = None ):
        """
        @param web: La dirección web a la que apunta el reporte
        @param printer: El objeto QPrinter en el que se imprime, esto es usado por si se desea alguna configuración especifica del reporte
        """
        super( frmReportes, self ).__init__( printer, parent )

        base = Reports.url

        if base == "":
            raise UserWarning( u"No existe una configuración para el servidor de reportes" )


        self.report = base + web + "&uname=" + user.LoggedUser.user + "&hash=" + user.LoggedUser.hash
        self.webview = QWebView()
        self.setWindowFlags( self.windowFlags() | Qt.WindowMaximizeButtonHint )




        self.txtSearch = QLineEdit()

        self.loaded = False


        self.webview.load( QUrl( self.report ) )
        self.progressbar = QProgressBar( self )




        self.paintRequested[QPrinter].connect( self.reprint )
        self.webview.loadFinished[bool].connect( self.on_webview_loadFinished )
        self.webview.loadProgress[int].connect( self.on_webview_loadProgress )



    def reprint( self, printer ):
        self.webview.print_( printer )

    def on_webview_loadProgress( self, progress ):
        self.progressbar.setValue( progress )

    def showEvent( self, _event ):
        if not self.loaded:
            self.progressbar.show()

    def on_webview_loadFinished( self, status ):
        if self.progressbar.isVisible():
            self.progressbar.hide()
        if not status:
            QMessageBox.critical( self, qApp.organizationName(), "El reporte no se pudo cargar" )
            logging.error( "No se pudo cargar el reporte: %s" % self.report )
            self.accept()

        self.loaded = True

        w = self.findChild( QPrintPreviewWidget )
        w.updatePreview()
Exemple #6
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.home_url = None
        self.zoom_factor = 1.0

        self.webview = WebView(self)
        self.connect(self.webview, SIGNAL("loadFinished(bool)"), self.load_finished)
        self.connect(self.webview, SIGNAL("titleChanged(QString)"), self.setWindowTitle)
        self.connect(self.webview, SIGNAL("urlChanged(QUrl)"), self.url_changed)

        previous_button = create_toolbutton(
            self, get_icon("previous.png"), tip=self.tr("Previous"), triggered=self.webview.back
        )
        next_button = create_toolbutton(self, get_icon("next.png"), tip=self.tr("Next"), triggered=self.webview.forward)
        home_button = create_toolbutton(self, get_icon("home.png"), tip=self.tr("Home"), triggered=self.go_home)
        zoom_out_button = create_toolbutton(
            self, get_icon("zoom_out.png"), tip=self.tr("Zoom out"), triggered=self.zoom_out
        )
        zoom_in_button = create_toolbutton(
            self, get_icon("zoom_in.png"), tip=self.tr("Zoom in"), triggered=self.zoom_in
        )
        refresh_button = create_toolbutton(self, get_icon("reload.png"), tip=self.tr("Reload"), triggered=self.reload)
        stop_button = create_toolbutton(self, get_icon("stop.png"), tip=self.tr("Stop"), triggered=self.webview.stop)
        stop_button.setEnabled(False)
        self.connect(self.webview, SIGNAL("loadStarted()"), lambda: stop_button.setEnabled(True))
        self.connect(self.webview, SIGNAL("loadFinished(bool)"), lambda: stop_button.setEnabled(False))

        progressbar = QProgressBar(self)
        progressbar.setTextVisible(False)
        progressbar.hide()
        self.connect(self.webview, SIGNAL("loadStarted()"), progressbar.show)
        self.connect(self.webview, SIGNAL("loadProgress(int)"), progressbar.setValue)
        self.connect(self.webview, SIGNAL("loadFinished(bool)"), progressbar.hide)

        label = QLabel(self.get_label())

        self.url_combo = UrlComboBox(self)
        self.connect(self.url_combo, SIGNAL("valid(bool)"), self.url_combo_activated)
        self.connect(self.webview, SIGNAL("iconChanged()"), self.icon_changed)

        self.find_widget = FindReplace(self)
        self.find_widget.set_editor(self.webview)
        self.find_widget.hide()

        find_button = create_toolbutton(
            self, icon="find.png", tip=translate("FindReplace", "Find text"), toggled=self.toggle_find_widget
        )
        self.connect(self.find_widget, SIGNAL("visibility_changed(bool)"), find_button.setChecked)

        hlayout = QHBoxLayout()
        for widget in (
            previous_button,
            next_button,
            home_button,
            find_button,
            label,
            self.url_combo,
            zoom_out_button,
            zoom_in_button,
            refresh_button,
            progressbar,
            stop_button,
        ):
            hlayout.addWidget(widget)

        layout = QVBoxLayout()
        layout.addLayout(hlayout)
        layout.addWidget(self.webview)
        layout.addWidget(self.find_widget)
        self.setLayout(layout)
class RipperWidget(SmoothWidget, ripper.Ripper):
    """ One-button multi-track ripper.
    """
    def __init__(self, parent=None):
        SmoothWidget.__init__(self, parent)
        ripper.Ripper.__init__(self)
        Layout = QVBoxLayout(self)

        self.discLabel = QLabel(self)
        Layout.addWidget(self.discLabel)

        # ONLY ONE BUTTON!
        self.button = QPushButton('Cancel', self)
        self.button.setEnabled(True)
        self.button.hide()
        QObject.connect(self.button, SIGNAL('clicked()'),
                        self.cancel)
        Layout.addWidget(self.button)

        self.catFrame = QFrame(self)
        self.catFrame.setFrameStyle(QFrame.StyledPanel)
        self.catFrame.hide()
        QHBoxLayout(self.catFrame)
        self.categories = CategoryButtons(self.catFrame)
        QObject.connect(self.categories, SIGNAL('selected(QString &)'),
                        self.start)
        self.catFrame.layout().addWidget(self.categories)
        Layout.addWidget(self.catFrame)
        
        self.progress = QProgressBar(self)
        self.progress.setRange(0, 100)
        self.progress.hide()
        Layout.addWidget(self.progress)

    def start(self, category):
        """ Should already have the track info. """
        self.genre = str(category)
        self._progress_data = {}
        self.disc_length = 0.0
        for i in range(self.count):
            sec = cd_logic.get_track_time_total(i)
            self._progress_data[i] = {'rip' : 0,
                                      'enc' : 0,
                                      'length' : sec}
            self.disc_length += sec
        self.rip_n_encode()

        text = '%s - %s' % (self.artist, self.album)
        self.discLabel.setText('Copying "'+text+'"...')
        self.button.show()
        self.progress.show()
        self.catFrame.hide()
            
    def cancel(self):        
        self.stop_request = True
        path = os.path.join(ripper.LIBRARY,
                            self.genre,
                            self.artist+' - '+self.album)
        os.system('rm -rf \"%s\"' % path)
        self.discLabel.setText('Canceled')
        self.button.hide()
        self.progress.hide()
        self.progress.setValue(0)
        self.emit(SIGNAL('canceled()'))

    def read_disc_info(self):
        self.discLabel.setText('Getting disc info...')
        ripper.Ripper.read_disc_info(self)

    def ripper_event(self, e):
        """ """
        event = QEvent(event_type(e.type))
        event.data = e.__dict__
        QApplication.instance().postEvent(self, event)

    def customEvent(self, e):
        if e.type() == event_type(ripper.CDDB_DONE):
            self.button.setEnabled(True)
            text = '%s - %s' % (self.artist, self.album)
            text += '           ( Select a category... )'
            self.discLabel.setText(text)
            self.catFrame.show()
            self.emit(SIGNAL('foundDiscInfo()'))
        elif e.type() == event_type(ripper.STATUS_UPDATE):
            self.updateProgress(e.data)
            self.emit(SIGNAL('status(QEvent *)'), e)

    def updateProgress(self, data):
        """
        assume rip and enc are equal in time.
        """
        state = data['state']
        tracknum = data['tracknum']
        percent = data['percent']
        goal_percents = self.count * 200

        item = self._progress_data[tracknum]
        if state == 'rip':
            item['rip'] = percent
        elif state == 'enc':
            item['enc'] = percent
        else:
            # err, etc...
            item['rip'] = 0
            item['enc'] = 0

        total = 0
        for i, v in self._progress_data.items():
            seconds = v['length']
            rip_perc = v['rip']
            enc_perc = v['enc']

            worth = seconds / self.disc_length
            rip_perc *= worth
            enc_perc *= worth
            total += rip_perc + enc_perc
            #print i, worth, rip_perc, enc_perc, total
        percent = total / 2
        self.progress.setValue(percent)

        if percent == 100:
            if self.is_ripping:
                print 'percent == 100 but still ripping?'
            if self.is_encoding:
                print 'percent == 100 but still encoding?'
            else:
                print 'percent == 100 and ripper finished'
            self.button.hide()
            self.progress.hide()
            text = 'Finished copying \"%s - %s\"' % (self.artist, self.album)
            self.discLabel.setText(text)
            self.emit(SIGNAL('doneRipping()'))
class Form(QMainWindow, Ui_MainWindow):
	"""IT Query Main Window."""

	def __init__(self, initIds, initErrIds, parent=None):
		"""Setup main window and populate with data(if given)."""
		super(Form, self).__init__(parent)
		self.setupUi(self)
		self.setWindowTitle("IT Query {0}".format(__version__))
		self.selectedIds = initIds
		self.errorIds = initErrIds

		LOG_LEVEL = logging.INFO
		currTime = time.localtime()
		runDate = time.strftime("%Y-%m-%d", currTime)
		self.dbPath = DB.Db.Info.Path
		LOG_FNAME = "{0}\{1}-{2}.{3}".format(self.dbPath, "itquery",
											 runDate, "txt")

		if LOG_LEVEL == logging.INFO:
			LOG_FORMAT = "%(asctime)s\t%(message)s"
		else:
			LOG_FORMAT = ("%(asctime)s - %(levelname)s - %(funcName)s "
						" - %(message)s")

		self.logger = logging.getLogger("itquery")
		self.logger.setLevel(LOG_LEVEL)
		self.handler = logging.FileHandler(LOG_FNAME)
		formatter = logging.Formatter(LOG_FORMAT)
		self.handler.setFormatter(formatter)
		self.logger.addHandler(self.handler)

		for action, slot in ((self.updateButton, self.updateSelection),
							(self.bionumericsButton, self.bnSelectFields),
							(self.itemTrackerButton, self.itSelectFields)):
			action.clicked.connect(slot)

		for action, slot in ((self.actionCollapseAll, self.collapseAll),
							(self.actionExpandAll, self.expandAll),
							(self.actionCollapseItem, self.collapseItem),
							(self.actionCherryPicking, self.cherryPicking),
							(self.actionExpandItem, self.expandItem),
							(self.actionSelectAll, self.selectAll),
							(self.actionSelectDNA, self.selectDNA),
							(self.actionSelectFrozenStock, self.selectFrozenStock),
							(self.actionSelectInvert, self.selectInvert),
							(self.actionSelectNone, self.selectNone),
							(self.actionGetAllSelected, self.getAllSelected),
							(self.actionRefresh, self.refresh),
							(self.actionAbout, self.about),
							(self.actionViewTree, self.viewTree),
							(self.actionClearLog, self.clearLog),
							(self.actionLegend, self.legend),
							(self.actionExportTraceList, self.exportTraceList),
							(self.actionExportDNAList, self.exportDNAList),
							(self.actionClose, self.close)):
			action.triggered.connect(slot)

		self.treeWidget.itemSelectionChanged.connect(self.updateInfo)
		self.viewMenu.addAction(self.logDockWidget.toggleViewAction())
		icon = QIcon(":/text-x-log.png")
		self.logDockWidget.toggleViewAction().setIcon(icon)
		self.actionSelectInBionumerics.toggled.connect(self.selectInBionumerics)

		self.userComboBox.currentIndexChanged.connect(self.userChanged)
		self.statusComboBox.currentIndexChanged.connect(self.statusChanged)

		self.treeActions = QActionGroup(self)
		self.treeActions.addAction(self.actionExpandItem)
		self.treeActions.addAction(self.actionCollapseItem)
		self.treeActions.addAction(self.actionExpandAll)
		self.treeActions.addAction(self.actionCollapseAll)

		self.selectActions = QActionGroup(self)
		self.selectActions.addAction(self.actionSelectAll)
		self.selectActions.addAction(self.actionSelectNone)
		self.selectActions.addAction(self.actionSelectInvert)
		self.selectActions.addAction(self.actionSelectDNA)
		self.selectActions.addAction(self.actionSelectFrozenStock)

		self.exportActions = QActionGroup(self)
		self.exportActions.addAction(self.actionExportDNAList)
		self.exportActions.addAction(self.actionExportTraceList)

		self.statusbar.setSizeGripEnabled(True)
		# user label at the right end of status bar
#		db = lims.DATABASE
		db = "No information"
		dbLabel  = QLabel("Database: <b>{0}</b>".format(db))
		self.statusbar.addPermanentWidget(dbLabel)
		user = os.environ.get("USERNAME") or "Demo user"
		label = QLabel("Logged in as: <b>{0}</b>".format(user))
		self.statusbar.addPermanentWidget(label)

		# restore main window state
		settings = QSettings()
		size = settings.value("MainWindow/Size",
							 QVariant(QSize(600, 500))).toSize()
		self.resize(size)
		position = settings.value("MainWindow/Position",
								 QVariant(QPoint(0, 0))).toPoint()
		self.move(position)
		self.restoreState(settings.value("MainWindow/State").toByteArray())
		splitterState = settings.value("MainWindow/SplitState").toByteArray()
		self.splitter.restoreState(splitterState)

		# selected fields
		self.dbName = bns.ConnectedDb.ConnectDb.GetList()
		regKey = "Bionumerics/{0}/SelFields".format(self.dbName)
		regBnFields = settings.value(regKey).toStringList()
		self.bnSelectedFields = [unicode(item) for item in regBnFields]

		regItFields = settings.value("ItemTracker/SelFields").toStringList()
		self.itSelectedFields = [unicode(item) for item in regItFields]

		# progress bar
		self.progressBar = QProgressBar(self)
		self.progressBar.setMaximumWidth(200)
		self.statusbar.insertPermanentWidget(0, self.progressBar)
		self.progressBar.hide()

		# initialize variables
		self.itemIds = {}
		self.itemNames = {}
		# bnFields - bionumerics information in the info panel
		self.bnFields = {}
		self.strainInfo = {}
		# maintains list of keys that are updated
		self.updatedStrains = []
		self.selectRadioButton.setChecked(True)
		self.itemProperties = {}
		self.tableResults = []
		self.getBnFields()
		self.mkInfo("{0}. Log: {1}".format(time.asctime(), LOG_FNAME))
		self.populatedTree = False
		self.populatedTable = False
		self.populatedCherry = False
		idField = "ItemTracker ID"  # Field with ItemTracker ID

		self.itemIdsAll, errors = bn.getItemIds(idField, DB.Db.Entries)
		if len(errors):
			for key, message in errors.iteritems():
				self.mkError("Key: {0}, {1}".format(key, message))
		self.database = None
		self.updateUi()

		self.proxyModel = SortFilterProxyModel(self)
		self.proxyModel.setDynamicSortFilter(True)
		self.cherryView.setModel(self.proxyModel)
		self.cherryView.setAlternatingRowColors(True)
		self.cherryView.setSortingEnabled(True)
		self.cherryView.verticalHeader().setVisible(False)
		self.cherryView.setEditTriggers(QAbstractItemView.NoEditTriggers)
		self.cherryView.horizontalHeader().setStretchLastSection(True)
		#self.populateTree() # testing
		QTimer.singleShot(0, self.populateTree)

	def bnSelectFields(self):
		"""Bionumerics field selection dialog."""
		try:
			fieldNames = bn.getFieldNames()
		except RuntimeError as e:
			self.mkError("Failed to get Bionumerics field names: {0}".format(e))

		dialog = selectfieldsdlg.selectFieldsDialog(fieldNames, self)
		if self.bnSelectedFields is not None:
			dialog.setSelected(self.bnSelectedFields)

		if dialog.exec_():
			self.bnSelectedFields = dialog.getSelected()
			self.updateInfo()

	def addCherryData(self, model, row):
		"""Inserts row into model"""
		model.insertRow(0)
		for position, value in enumerate(row):
			model.setData(model.index(0, position), value)

	def createCherryModel(self, data, parent):
		"""Creates a model for the tableview using data retrieved from the
		cherry picking database.

		"""
		total = len(data)
		self.progressBar.setMaximum(total)
		self.progressBar.show()
		model = QStandardItemModel(0, len(CHERRY_COLUMNS), parent)
		for position, column in enumerate(CHERRY_COLUMNS):
			model.setHeaderData(position, Qt.Horizontal, column)

		# get additional data for each item
		keys = [item[CHERRY_COLUMNS.index("Key")] for item in data]
		itemIds = []
		missing = []
		itemIdsAll = dict((v, k) for k, v in self.itemIdsAll.iteritems())
		for key in keys:
			if key in itemIdsAll:
				itemIds.append(itemIdsAll[key])
			else:
				missing.append(key)

		if len(missing):
			msg = ("Keys exist in cherry picking database but absent "
				"in Bionumerics {0}".format(", ".join(missing)))
			self.mkWarn(msg)

		if not len(itemIds):
			msg = "No entries in cherry picking database"
			self.statusBar().showMessage(msg, 5000)
			self.mkInfo(msg)
			return None
		itemIds = list(set(itemIds))
		(dnaData, noData, errors) = lims.GetNewestDNAForCherryPicking(itemIds)
		if len(noData):
			msg = ", ".join(str(item) for item in noData)
			self.mkWarn("{0}: {1}".format("No DNA's for these strains", msg))

		if len(errors):
			msg = ", ".join(errors)
			self.mkError(msg)

		for count, result in enumerate(data):
			result = list(result)
			key = result[0]
			if key in itemIdsAll:
				self.progressBar.setValue(count)
				#QApplication.processEvents()
				parentID = itemIdsAll[key]

				if parentID in dnaData:
					properties = dnaData[parentID]
					for value in ("ItemName", "DNA concentration", "Volume",
								 "Freezer", "Rack", "Shelf", "PlateRack",
								  "Position"):
						if value in properties:
							result.append(properties[value])
						else:
							result.append("")
			self.addCherryData(model, result)
		return model

	def cherryPicking(self):
		"""Populate the cherry picking table"""
		if self.populatedCherry:
			if not self.stackedWidget.currentIndex() == 2:
				self.stackedWidget.setCurrentIndex(2)
				self.updateUi()
			return
		self.statusbar.showMessage("Getting data from cherry picking database")

		db = DB.Db.Info.Name
		cherryData = pgdb.get_data(db)

		if not len(cherryData):
			msg = "No cherry picking entries for this database"
			self.statusbar.showMessage(msg, 5000)
			self.mkInfo(msg)
			self.stackedWidget.setCurrentIndex(2)
			self.updateUi()
			return

		self.userComboBox.clear()
		self.statusComboBox.clear()
		# filter combo boxes
		for label, combo in (("Username", self.userComboBox),
							("Status", self.statusComboBox)):
			position = CHERRY_COLUMNS.index(label)
			comboItems = set([item[position] for item in cherryData])
			combo.addItem("All")
			combo.addItems(list(comboItems))

		self.proxyModel.traceStatus = self.statusComboBox.currentText()
		self.cherryView.reset()
		self.cherryView.setDisabled(True)
		self.statusbar.showMessage("Getting data from ItemTracker")

		model = self.createCherryModel(cherryData, self)
		if not model:
			self.cherryView.setEnabled(False)
			self.filterGroupBox.setDisabled(True)
		else:
			self.proxyModel.setSourceModel(model)
			self.cherryView.setEnabled(True)
			self.filterGroupBox.setEnabled(True)

		self.cherryView.resizeColumnsToContents()
		self.updateCounts()
		self.stackedWidget.setCurrentIndex(2)  # switch view to table
		self.statusbar.clearMessage()
		self.progressBar.setValue(len(cherryData))
		self.progressBar.hide()
		self.populatedCherry = True
		self.updateUi()

	def statusChanged(self):
		"""Filter cherry picking based on current trace status from combo box."""
		self.proxyModel.setTraceStatus(self.statusComboBox.currentText())
		self.updateCounts()

	def userChanged(self):
		"""Filter cherry picking based on current user from combo box."""
		user = self.userComboBox.currentText()
		if user == "All":
			user = "******"
		regExp = QRegExp(user, Qt.CaseInsensitive, QRegExp.RegExp2)
		self.proxyModel.setFilterRegExp(regExp)
		self.updateCounts()

	def updateCounts(self):
		"""Update counts of strains, traces and DNA in cherry picking"""
		strains = []
		traces = self.proxyModel.rowCount()
		dna = []

		for i in range(traces):
			for field, totals in (("Key", strains), ("DNA", dna)):
				index = self.proxyModel.index(i, CHERRY_COLUMNS.index(field))
				data = self.proxyModel.data(index).toString().trimmed()
				if len(data) and data not in totals:
					totals.append(data)

		self.strainsLcdNumber.display(len(strains))
		self.tracesLcdNumber.display(traces)
		self.dnaLcdNumber.display(len(dna))

	def getSaveFile(self, caption=""):
		"""Opens the save file dialog and returns the file name."""
		if not len(caption):
			caption = "Save File As"

		fn = QFileDialog.getSaveFileName(self, caption, self.dbPath,
										 "Text files (*.txt);;All Files (*.*)")
		if fn:
			if QFileInfo(fn).suffix().isEmpty():
				fn += ".txt"
		return fn

	def exportTextFile(self, fh=None, header=None, data=None):
		"""Writes data to the given file. Accepts column names and the data as
		arguments

		"""
		if not fh:
			self.mkError("Could not open file for writing")
			return

		if not data:
			data = []

		if not len(data):
			self.mkWarn("No data to write")
			return

		fname = QFile(fh)
		if fname.open(QFile.WriteOnly | QFile.Text):
			txt = QTextStream(fname)
			if header:
				txt << ", ".join(col for col in header)
			txt << "\n"
			txt << "\n".join(", ".join(item) for item in data)

			msg = "File export complete: {0}".format(str(fname.fileName()))
			self.mkSuccess(msg)

	def exportDNAList(self):
		"""Export list of DNA's displayed in cherry picking."""
		data = []
		keys = []

		columns = CHERRY_COLUMNS[:]
		excludeColumns = ["Gene", "Orientation"]
		exclude = []

		for item in excludeColumns:
			exclude.append(CHERRY_COLUMNS.index(item))
			columns.remove(item)

		keyIndex = CHERRY_COLUMNS.index("Key")
		dnaIndex = CHERRY_COLUMNS.index("DNA")
		for i in range(0, self.proxyModel.rowCount()):
			# continue if key exists in keys
			index = self.proxyModel.index(i, keyIndex)
			key = self.proxyModel.data(index).toString()

			if key in keys:
				continue
			# continue if DNA column is empty
			index = self.proxyModel.index(i, dnaIndex)
			dna = self.proxyModel.data(index).toString()

			if dna.isEmpty():
				continue
			row = []
			for j in range(self.proxyModel.columnCount()):
				if j in exclude:
					continue
				index = self.proxyModel.index(i, j)
				value = self.proxyModel.data(index).toString()

				if not value.isEmpty():
					row.append(str(value))
				else:
					row.append("")
			data.append(row)
			keys.append(key)

		fh = self.getSaveFile("Export DNA List")
		self.exportTextFile(fh, columns, data)

	def exportTraceList(self):
		"""Export list of traces displayed in cherry picking."""
		data = []
		for i in range(0, self.proxyModel.rowCount()):
			row = []
			for j in range(self.proxyModel.columnCount()):
				index = self.proxyModel.index(i, j)
				value = self.proxyModel.data(index).toString()
				if not value.isEmpty():
					row.append(str(value))
				else:
					row.append("")
			data.append(row)

		fh = self.getSaveFile("Export Trace List")
		columns = CHERRY_COLUMNS[:]
		self.exportTextFile(fh, columns, data)

	def clearLog(self):
		"""Clears the log window"""
		self.logBrowser.clear()

	def closeEvent(self, event):
		"""Called on closing the window. Save settings and exit."""
		self.handler.close()
		self.logger.removeHandler(self.handler)

		if self.okToContinue():
			settings = QSettings()
			settings.setValue("MainWindow/Size", QVariant(self.size()))
			settings.setValue("MainWindow/Position", QVariant(self.pos()))
			settings.setValue("MainWindow/State", QVariant(self.saveState()))
			settings.setValue("MainWindow/SplitState",
							 self.splitter.saveState())

			bnSelectedFields = QVariant(self.bnSelectedFields) \
			if self.bnSelectedFields else QVariant()
			regkey = "Bionumerics/{0}/SelFields".format(self.dbName)
			settings.setValue(regkey, bnSelectedFields)

			itSelectedFields = QVariant(self.itSelectedFields) \
			if self.itSelectedFields else QVariant()
			settings.setValue("ItemTracker/SelFields", itSelectedFields)
		else:
			event.ignore()

	def collapseItem(self):
		"""Collapse selected item."""
		try:
			selected = self.treeWidget.selectedItems()[0]
		except IndexError:
			selected = None
			self.statusbar.showMessage("No item selected", 2000)

		if selected:
			self.treeWidget.collapseItem(selected)

	def collapseAll(self):
		"""Collapse all items."""
		self.treeWidget.collapseAll()

	def disableWidgets(self, widgets):
		"""Disable group of widgets. Does not change visibility."""
		for widget in widgets:
			if widget.isEnabled():
				widget.setDisabled(True)

	def enableWidgets(self, widgets):
		"""Enable group of widgets. Set visible if not visible."""
		for widget in widgets:
			if not widget.isEnabled():
				widget.setEnabled(True)
			if not widget.isVisible():
				widget.setVisible(True)

	def expandItem(self):
		"""Expand selected item."""
		try:
			selected = self.treeWidget.selectedItems()[0]
		except IndexError:
			selected = None
			self.statusbar.showMessage("No item selected", 2000)

		if selected:
			self.treeWidget.expandItem(selected)

	def expandAll(self):
		"""Expands all items."""
		self.treeWidget.expandAll()

	def getBnFields(self):
		"""Get bionumerics field information required for the info panel."""
		bnFields = bn.getFieldNames()
		strainFields = ["Strain", "STRAIN"]

		for field in strainFields:
			if (field in bnFields) and (field not in self.bnSelectedFields):
				self.bnSelectedFields.append(field)

		for key in self.selectedIds.values():
			if not self.bnFields.get(key):
				self.bnFields[key] = bn.getSelectedFields(key, bnFields)

	def getParent(self, item):
		"""Returns the top level parent of an item."""
		parentItem = None

		while item.parent():
			parentItem = item.parent()
			item = parentItem
		return parentItem

	def getData(self, items, itemid):
		"""Returns parent and children for data received from GetDictionary."""
		if len(items):
			children = items[itemid].keys()
			yield itemid, children
			items = items[itemid]

			for child in children:
				for res in self.getData(items, child):
					yield res
		return

	def getAllItemIds(self):
		"""Gets all ItemTracker IDs in the current Bionumerics database."""
		itemIds = {}
		field = "ItemTracker ID"
		value = None
		for i in range(len(DB.Db.Entries)):
			value = DB.Db.Entries[i].Field(field).Content
			# bugfix: don't display if ItemTracker ID contains spaces
			value = value.strip()
			if not len(value):
				continue

			key = DB.Db.Entries[i].Key
			key = key.strip()
			if key in itemIds:
				itemIds.pop(key)
				msg = "Duplicate keys in database: {0}. Not processed".format(key)
				self.mkWarn(msg)
				continue

			try:
				value = int(value)
			except (ValueError, TypeError):
				self.mkWarn("Invalid ItemTracker ID {0} for entry "
						"{1} in Bionumerics".format(value, key))

			if isinstance(value, int):
				if value in itemIds.values():
					msg = ("Duplicate ItemTracker ID: {0}. "
						"Keys: {1}, ".format(value, key))
					for k, v in itemIds.items():
						if v == value:
							itemIds.pop(k)
							msg += k
					self.mkWarn(msg)
				else:
					itemIds[key] = value

		return itemIds

	def getAllSelected(self):
		"""Get all selected items by user."""
		if self.populatedTable:
			self.stackedWidget.setCurrentIndex(1)
			self.updateUi()
			return
		msg = "Getting all selected entries from ItemTracker. Please wait..."
		self.statusbar.showMessage(msg)

		if len(self.itemIdsAll):
			try:
				self.tableResults = \
				lims.SelectAllselectedEntries(self.itemIdsAll.keys())
			except:
				raise RuntimeError
		else:
			self.mkInfo("No ItemTracker IDs to process")

		if not len(self.tableResults):
			user = os.environ.get("USERNAME")
			msg = "No selected entries for user {0}".format(user)
			self.statusbar.showMessage(msg, 5000)
			self.mkInfo(msg)
			self.stackedWidget.setCurrentIndex(1)
			self.populatedTable = False
			self.updateUi()
		else:
			QTimer.singleShot(0, self.populateTable)

	def getItemtrackerFields(self):
		"""Returns all ItemTracker fields returned from GetDictionary."""
		fields = []
		alwaysFields = ["ItemID", "ItemName", "Position"]

		for item in self.itemProperties:
			for field in self.itemProperties[item].keys():
				if (field not in fields) and (field not in alwaysFields):
					fields.append(field)
		return fields

	def getWidget(self):
		"""Returns the current active widget."""
		index = self.stackedWidget.currentIndex()
		if index == 0:
			widget = self.treeWidget
		elif index == 1:
			widget = self.selectedWidget
		elif index == 2:
			widget = self.cherryView

		return widget

	def about(self):
		"""About box."""
		import platform
		msg = """\
		<b>IT Query</b> version {0} <p>An interface to query
		ItemTracker from Bionumerics</p>Python {1} - Qt {2} -
		PyQt {3} on {4}\
		""".format(__version__, platform.python_version(),
				QT_VERSION_STR, PYQT_VERSION_STR, platform.system())

		msg += """<br>Icons from the
		<a href="http://www.oxygen-icons.org/">Oxygen project</a>
		</p>"""
		QMessageBox.about(self, "About IT Query", msg)

	def legend(self):
		"""A simple dialog displaying the color legend used in treeview."""
		dialog = legenddlg.legendDialog(self)
		dialog.exec_()

	def itSelectFields(self):
		"""ItemTracker field selection dialog."""
		fieldNames = self.getItemtrackerFields()
		dialog = selectfieldsdlg.selectFieldsDialog(fieldNames, self)

		if self.itSelectedFields is not None:
			dialog.setSelected(self.itSelectedFields)

		if dialog.exec_():
			self.itSelectedFields = dialog.getSelected()
			self.updateInfo()

	def mkWarn(self, msg):
		"""Orange color"""
		bgColor = "235,115,49"
		self.mkTable(bgColor, "WARNING", msg)

	def mkError(self, msg):
		"""Red color"""
		bgColor = "226,8,0"
		self.mkTable(bgColor, "ERROR", msg)

	def mkSuccess(self, msg):
		"""Green color"""
		bgColor = "55,164,44"
		self.mkTable(bgColor, "SUCCESS", msg)

	def mkInfo(self, msg):
		"""Blue color"""
		bgColor = "0,87,174"
		self.mkTable(bgColor, "INFO", msg)

	def mkTable(self, bgColor, status, msg):
		"""Formats message displayed in the log window."""
		formatStatus = ('<font style="color:rgb({0})"><strong>{1}</strong>'
					'</font>'.format(bgColor, status))
		self.logBrowser.append("{0}: {1}".format(formatStatus, msg))

	def okToContinue(self):
		"""Check before closing."""
		if len(self.updatedStrains):
			reply = QMessageBox(QMessageBox.Question,
			"Selection", "Entry selection in Bionumerics",
			QMessageBox.NoButton, self)

			originalButton = QPushButton("Keep Original Selection")
			updatedButton = QPushButton("Updated Items Only")
			cancelButton = QPushButton("Cancel")

			reply.addButton(originalButton, QMessageBox.ActionRole)
			reply.addButton(updatedButton, QMessageBox.ActionRole)
			reply.addButton(cancelButton, QMessageBox.RejectRole)
			reply.exec_()

			if reply.clickedButton() == cancelButton:
				return False
			elif reply.clickedButton() == originalButton:
				bn.selectEntries(self.selectedIds.values() +\
								 self.errorIds.keys())
			elif reply.clickedButton() == updatedButton:
				bn.selectEntries(self.updatedStrains)
		return True

	def populateTable(self):
		"""Populates table with data from ItemTracker."""
		self.selectedWidget.clear()
		self.selectedWidget.setSortingEnabled(False)
		numRows = len(self.tableResults)
		self.mkInfo("Selected items in ItemTracker: {0}".format(numRows))

		self.selectedWidget.setAlternatingRowColors(True)
		header = ["ItemID", "StrainID", "ItemType", "ItemName", "BacteriaItemID"]
		self.selectedWidget.setColumnCount(len(header))
		self.selectedWidget.setHeaderLabels(header)

		# use result and populate table
		for result in self.tableResults:
			properties = [unicode(i) for i in result]
			item = QTreeWidgetItem(self.selectedWidget, properties)
			item.setCheckState(0, Qt.Unchecked)

		self.selectedWidget.setSortingEnabled(True)
		for i in range(len(header)):
			self.selectedWidget.resizeColumnToContents(i)
		self.stackedWidget.setCurrentIndex(1) # switch view to table
		self.statusbar.clearMessage()
		self.populatedTable = True
		self.updateUi()

	def populateTree(self):
		"""Populates tree view with information from ItemTracker."""
		if len(self.errorIds):
			self.mkError("{0} entries do not have valid "
			"ItemTracker IDs in Bionumerics.".format(len(self.errorIds)))

			for key, msg in self.errorIds.iteritems():
				self.mkError("KEY: {0} {1}".format(key, msg))

		if not len(self.selectedIds):
			self.statusbar.showMessage("No items to process", 5000)
			return

		parents = {}
		headers = ["Items", "Selected", "SelectedBy", "Viability", "Volume",
				 "DNA concentration", "UserName", "TubePresent", "InputDate",
				 "AlternID", "Status"]

		self.treeWidget.setItemsExpandable(True)
		self.treeWidget.setAlternatingRowColors(True)
		self.treeWidget.setColumnCount(len(headers))
		self.treeWidget.setHeaderLabels(headers)

		msg = "Getting information from ItemTracker. Please wait..."
		self.statusbar.showMessage(msg)

		self.progressBar.setMinimum(0)
		self.progressBar.setMaximum(0)
		self.progressBar.show()

		(treeData, self.itemProperties,
		 message) = lims.GetDictionary((self.selectedIds.keys()))

		if len(message):
			for msg in message:
				self.mkError("ItemTracker error: {0}".format(msg))

		if not len(treeData):
			self.mkError("Could not get data from ItemTracker for"
						"selected entries")
			self.statusBar().clearMessage()
			self.progressBar.hide()
			self.updateUi()
			return

		# bugfix: If ItemType property does not exist for the first item
		# self.database is not set and tree view is not updated.
		db = None
		if not self.database:
			for item in self.itemProperties.values():
				try:
					db = item["ItemType"]
				except KeyError:
					pass

				if db == "Salmonella":
					self.database = db
					break
				elif db == "Listeria":
					self.database = db
					break

		self.progressBar.setMaximum(len(treeData))
		count = 0
		for key, value  in treeData.iteritems():
			count += 1
			self.progressBar.setValue(count)
			if not(value and isinstance(value, dict)):
				self.mkWarn("No data returned for key {0}".format(key))
				continue

			items = {}
			items[key] = value
			for results in self.getData(items, key):
				parent = parents.get(results[0])

				if not parent:
					parent_id = self.selectedIds[results[0]]
					self.strainInfo[parent_id] = {self.database:[],
												"Frozen Stock":[], "DNA":[]}
					parent = QTreeWidgetItem(self.treeWidget,
					[unicode(parent_id)])

					brush = QBrush()
					brush.setColor(Qt.blue)
					parent.setForeground(0, brush)
					parent.setIcon(0, QIcon(":/branch-closed.png"))
					parent.setData(0, Qt.CheckStateRole, QVariant())
					parents[results[0]] = parent

				for children in results[1]:
					itemName = self.itemProperties[children]["ItemName"]
					if not self.itemIds.get(itemName):
						self.itemIds[itemName] = children

					childprops = []
					childprops.append(unicode(itemName))

					for header in headers[1:]:
						try:
							childprop = self.itemProperties[children][header]

							if childprop is None or childprop == "":
								childprops.append(unicode(""))
							else:
								childprops.append(unicode(childprop))
						except KeyError:
							childprops.append(unicode(""))
							continue

					childs = parents.get(children)
					if not childs:
						childs = QTreeWidgetItem(parent, childprops)

						if self.itemProperties[children]["TubePresent"] == "-":
							childs.setBackgroundColor(0, QColor(232, 87, 82))
							childs.setForeground(0, QColor(255, 255, 255))

						if self.itemProperties[children]["Selected"] == "yes":
							childs.setBackgroundColor(0, QColor(119, 183, 83))
							childs.setForeground(0, QColor(255, 255, 255))

						itype = self.itemProperties[children]["ItemType"]
						if itype:
							self.strainInfo[parent_id][itype].append(itemName)
						parents[children] = childs
					childs.setCheckState(0, Qt.Unchecked)

		self.treeWidget.expandAll()
		for i in range(len(headers)):
			self.treeWidget.resizeColumnToContents(i)
		if not self.treeWidget.isEnabled():
			self.treeWidget.setEnabled(True)
		self.mkInfo("Processed <b>{0}</b> entries".format(len(treeData)))

		self.progressBar.setValue(len(treeData))
		self.progressBar.hide()
		self.populatedTree = True
		self.updateUi()
		self.statusbar.showMessage("Ready", 5000)

	def selectAll(self):
		"""All items are selected (checked)."""
		index = self.stackedWidget.currentIndex()
		widget = self.getWidget()
		it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.NotChecked)
		count = 0
		if index == 0:
			while it.value():
				if it.value().parent():
					it.value().setCheckState(0, Qt.Checked)
					count += 1
				it += 1
		elif index == 1:
			while it.value():
				it.value().setCheckState(0, Qt.Checked)
				count += 1
				it += 1
		if count:
			self.statusbar.showMessage("Selected {0} items".format(count), 3000)

	def selectDNA(self):
		"""Select all DNA items."""
		self.selectItems("DNA")

	def selectFrozenStock(self):
		"""Select all Frozen Stock items."""
		self.selectItems("Frozen Stock")

	def selectNone(self):
		"""Clears the selection."""
		widget = self.getWidget()
		it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.Checked)
		while it.value():
			it.value().setCheckState(0, Qt.Unchecked)
			it += 1

	def selectInvert(self):
		"""Inverts the selection."""
		index = self.stackedWidget.currentIndex()
		widget = self.getWidget()
		it = QTreeWidgetItemIterator(widget)

		if index == 0:
			while it.value():
				if it.value().parent():
					if it.value().checkState(0) == Qt.Checked:
						it.value().setCheckState(0, Qt.Unchecked)
					else:
						it.value().setCheckState(0, Qt.Checked)
				it += 1
		else:
			while it.value():
				if it.value().checkState(0) == Qt.Checked:
					it.value().setCheckState(0, Qt.Unchecked)
				else:
					it.value().setCheckState(0, Qt.Checked)
				it += 1

	def selectItems(self, itemType):
		"""Select all items of a given ItemType."""
		self.statusbar.showMessage("Selecting all {0}'s. "
								"Please wait...".format(itemType))

		items = []
		itemsAll = []
		index = self.stackedWidget.currentIndex()

		if index == 0:
			position = 0
			items = [item[itemType] for item in self.strainInfo.values()]
			for item in items:
				if len(item):
					itemsAll += item
		else:
			position = 3
			for item in self.tableResults:
				if item[2] == itemType:
					itemsAll.append(item[3])

		if not len(itemsAll):
			self.statusbar.showMessage("No {0}'s in list".format(itemType), 5000)
			return
		self.selectNone()
		widget = self.getWidget()
		it = QTreeWidgetItemIterator(widget)
		while it.value():
			if it.value().text(position) in itemsAll:
				it.value().setCheckState(0, Qt.Checked)
			it += 1
		self.statusbar.showMessage("Selected {0} {1}'s".format(len(itemsAll),
															 itemType), 3000)

	def selectInBionumerics(self, on):
		"""Selects Bionumerics entries with checked items from table view
		(get all selected)

		"""
		actionGroup = QActionGroup(self)
		actionGroup.addAction(self.actionViewTree)
		actionGroup.addAction(self.refresh_action)
		actionGroup.addAction(self.actionSelectAll)
		actionGroup.addAction(self.actionSelectInvert)
		actionGroup.addAction(self.actionSelectNone)
		actionGroup.addAction(self.actionSelectDNA)
		actionGroup.addAction(self.actionSelectFrozenStock)

		if on:
			actionGroup.setEnabled(False)
			if not len(self.itemNames):
				self.itemNames = bn.createIdMap()

			it = QTreeWidgetItemIterator(self.selectedWidget,
										 QTreeWidgetItemIterator.Checked)
			checkedItems = []
			while it.value():
				parentCode = unicode(it.value().text(4))
				bnStrain = self.itemNames[int(parentCode)]

				if bnStrain not in checkedItems:
					checkedItems.append(bnStrain)
				it += 1

			if len(checkedItems):
				bn.selectEntries(checkedItems)
			else:
				self.statusbar.showMessage("No items checked", 3000)
		else:
			actionGroup.setEnabled(True)
			bn.selectEntries(self.selectedIds.values() + self.errorIds.keys())

	def updateSelection(self):
		"""Updates selection status in ItemTracker."""
		if self.actionSelectInBionumerics.isChecked():
			self.selectInBionumerics(False)
			self.actionSelectInBionumerics.setChecked(False)

		self.updateButton.setEnabled(False)
		self.statusbar.showMessage("Updating selection. Please wait...")

		if self.selectRadioButton.isChecked():
			selectedAction = "SELECT"
		elif self.deselectRadioButton.isChecked():
			selectedAction = "DESELECT"

		checkedItems = {}
		updatedItems = []
		failedItems = []

		index = self.stackedWidget.currentIndex()
		widget = self.getWidget()
		it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.Checked)

		if index == 0:
			while it.value():
				itemName = unicode(it.value().text(0))
				itemId = self.itemIds[itemName]
				checkedItems[itemName] = itemId
				parentItem = self.getParent(it.value())
				strain =  unicode(parentItem.text(0))
				if strain not in self.updatedStrains:
					self.updatedStrains.append(strain)
				it += 1
		elif index == 1:
			if not len(self.itemNames):
				self.itemNames = bn.createIdMap()

			while it.value():
				itemId = unicode(it.value().text(0))
				itemName = unicode(it.value().text(3))
				checkedItems[itemName] = int(itemId)

				parentCode = unicode(it.value().text(4))
				strain = self.itemNames[int(parentCode)]
				if strain not in self.updatedStrains:
						self.updatedStrains.append(strain)
				it += 1

		if not len(checkedItems):
			self.statusbar.showMessage("No items checked", 5000)
			self.updateButton.setEnabled(True)
			return

		for itemName, itemId in checkedItems.iteritems():
			if selectedAction == "SELECT":
				result = lims.SelectItem(itemId)
			elif selectedAction == "DESELECT":
				result = lims.UnselectItem(itemId)

			if not len(result):
				updatedItems.append(itemName)
			else:
				failedItems.append(itemName)

		if len(updatedItems):
			self.mkSuccess("{0}ED {1} items".format(selectedAction,
												 len(updatedItems)))
			self.logBrowser.append("{0}".format(", ".join(updatedItems)))
			self.logger.info("{0}\t{1}".format(selectedAction, ", ".join(updatedItems)))
		if len(failedItems):
			self.mkError("{0} failed for {1} items".format(selectedAction,
														 len(failedItems)))

			self.logBrowser.append("{0}".format(", ".join(failedItems)))
			self.logger.info("{0}\t{1}".format(selectedAction,
											 ", ".join(failedItems)))

		self.updateButton.setEnabled(True)
		if len(updatedItems) or len(failedItems):
			self.populatedTree = False
			self.populatedTable = False
			self.refresh()

	def updateUi(self):
		"""Updates interface based on the view."""
		index = self.stackedWidget.currentIndex()

		# only show export actions in cherry picking
		if index != 2:
			widgets = [self.exportToolBar, self.exportActions]
			self.disableWidgets(widgets)
			for widget in widgets:
				widget.setVisible(False)

		# disable select menu in cherry picking (not implemented)
		if index == 2:
			self.selectMenu.setEnabled(False)
		else:
			self.selectMenu.setEnabled(True)

		if index == 0:  # Tree View
			self.disableWidgets([self.actionViewTree,
								self.actionSelectInBionumerics])
			self.enableWidgets([self.actionGetAllSelected,
							self.actionCherryPicking])

			for widget in [self.actionSelectInBionumerics,
						self.getSelectedToolBar]:
				widget.setVisible(False)

			#self.fieldsGroupBox.setVisible(True)
			widgets = [self.widget, self.treeWidget, self.selectGroupBox,
					self.fieldsGroupBox, self.actionLegend, self.treeToolBar,
					self.treeActions, self.selectActions]
			for widget in widgets:
				if not widget.isVisible():
					widget.setVisible(True)

			if self.populatedTree:
				self.enableWidgets(widgets)
			else:
				self.disableWidgets(widgets)

			try:
				self.treeWidget.selectedItems()[0]
			except IndexError:
				self.infoBrowser.setDisabled(True)

			self.fieldsGroupBox.setEnabled(self.infoBrowser.isEnabled())

		elif index == 1:
			self.widget.setVisible(True)
			self.enableWidgets([self.actionViewTree, self.actionCherryPicking])
			self.actionSelectInBionumerics.setVisible(True)
			self.getSelectedToolBar.setVisible(True)

			for widget in [self.actionLegend, self.fieldsGroupBox,
						 self.treeToolBar, self.treeActions]:
				widget.setVisible(False)

			self.disableWidgets([self.actionGetAllSelected, self.actionLegend,
								 self.treeToolBar, self.treeActions])

			widgets = [self.widget, self.selectedWidget, self.selectGroupBox,
					self.actionSelectInBionumerics, self.getSelectedToolBar,
					self.selectActions]

			if self.populatedTable:
				self.enableWidgets(widgets)
			else:
				self.disableWidgets(widgets)

		elif index == 2:
			self.widget.setVisible(False)  # ItemTracker and field selection
			self.actionCherryPicking.setEnabled(False)
			self.exportToolBar.setVisible(True)
			self.exportActions.setVisible(True)

			for action in [self.actionViewTree, self.actionGetAllSelected]:
				action.setEnabled(True)

			widgets = [self.selectActions, self.actionSelectInBionumerics,
					 self.actionLegend, self.treeActions, self.treeToolBar,
					 self.getSelectedToolBar]
			self.disableWidgets(widgets)
			for widget in widgets:
				widget.setVisible(False)

			widgets = [self.cherryView, self.filterGroupBox, self.lcdGroupBox,
					 self.exportActions, self.exportToolBar]

			if self.populatedCherry:
				self.enableWidgets(widgets)
			else:
				self.disableWidgets(widgets)

	def updateInfo(self):
		"""Infobar displaying ItemTracker and Bionumerics fields."""
		content = ('<table border="0" cellspacing="0" '
		'cellpadding="5" width="100%">')
		self.infoBrowser.clear()
		try:
			selected = self.treeWidget.selectedItems()[0]
		except IndexError:
			return
		else:
			self.infoBrowser.setEnabled(True)
			self.fieldsGroupBox.setEnabled(True)
		try:
			parentName = self.getParent(selected).text(0)
		except AttributeError:
			parentName = None

		if parentName:
			itemName = unicode(selected.text(0))
			itemId = self.itemIds[itemName]

			if itemId:
				content += """\
				<tr bgcolor="#85026C">
					<th colspan="2" align="left">
						<font color="white">ITEMTRACKER</font>
					</th>
				</tr>\
				"""
				count = 0
				for field, value in (("Strain", parentName),
									 ("Item&nbsp;Name", itemName),
									 ("Item&nbsp;ID", itemId)):
					if count % 2 == 0:
						content += """\
						<tr>
							<td>{0}</td>
							<td>{1}</td>
						</tr>\
						""".format(field, value)
					else:
						content += """\
						<tr bgcolor="#eee">
							<td>{0}</td>
							<td>{1}</td>
						</tr>\
						""".format(field, value)
					count += 1
			try:
				properties = self.itemProperties[int(itemId)]
			except KeyError:
				self.mkWarn("Could not get properties for "
				"ItemTracker ID {0}".format(itemId))

			if len(properties):
				try:
					location = properties["Position"]
				except KeyError:
					location = []
				if len(location):
					for field, value in (("Freezer", location[0]),
										 ("Rack", location[1]),
										 ("Shelf", location[2]),
										 ("Plate Rack", location[3]),
										 ("Position", location[4])):
						if count % 2 == 0:
							content += """\
							<tr>
								<td>{0}</td>
								<td>{1}</td>
							</tr>\
							""".format(field, value)
						else:
							content += """\
							<tr bgcolor="#eee">
								<td>{0}</td>
								<td>{1}</td>
							</tr>\
							""".format(field, value)
						count += 1

				if len(self.itSelectedFields):

					for itField in self.itSelectedFields:
						try:
							itemProperty = properties[itField]
						except KeyError:
							itemProperty = ""

						if count % 2 == 0:
							content += """\
							<tr>
								<td>{0}</td>
								<td>{1}</td>
							</tr>\
							""".format(itField, itemProperty)
						else:
							content += """\
							<tr bgcolor="#eee">
								<td>{0}</td>
								<td>{1}</td>
							</tr>\
							""".format(itField, itemProperty)
						count += 1
			else:
				content += """\
				<tr>
					<td colspan="2">No information</td>
				</tr>"""

			self.infoBrowser.setHtml(QString(content))
			content += """\
			<tr bgcolor="#CF4913">
				<th colspan="2" align="left">
					<font color="white">BIONUMERICS</font>
				</th>
			</tr>\
			"""
			strainInfo = {}
			try:
				strainInfo = self.bnFields.get(unicode(parentName))
			except KeyError:
				self.mkWarn("Could not get information for {0}".format(parentName))

			if len(strainInfo):
				count = 0
				for field in self.bnSelectedFields:

					if count % 2 == 0:
						content += """\
						<tr>
							<td>{0}</td>
							<td>{1}</td>
						</tr>\
						""".format(field, strainInfo[field])
					else:
						content += """\
						<tr bgcolor="#eee">
							<td>{0}</td>
							<td>{1}</td>
						</tr>\
						""".format(field, strainInfo[field])
					count += 1
			else:
				self.mkWarn("No information for {0}".format(parentName))
			content += "</table>"
		else:
			strainName = unicode(selected.text(0))
			itemId = None
			for ids, keys in self.selectedIds.iteritems():
				if keys == strainName:
					itemId = ids
					break
			if not itemId:
				self.infoBrowser.setHtml(QString(content))
				return

			content = """\
			<table border="0" cellpadding="5" cellspacing="0" width="100%">
				<tr bgcolor="#85026C">
					<th colspan="2" align="left">
						<font color="white">ITEMTRACKER</font>
					</th>
				</tr>
				<tr bgcolor="#eee">
					<td>AlternID</td>
					<td>{0}</td>
				</tr>
				<tr>
					<td>OriginalID</td>
					<td>{1}</td>
				</tr>\
				""".format(self.itemProperties[itemId]["AlternID"],
			self.itemProperties[itemId]["OriginalID"])

			content += "</table>"
			content += """\
			<table border="0" cellpadding="5" cellspacing="0" width="100%">
				<tr bgcolor="#BF0361">
					<th align="left">
						<font color="white">{0}</font>
					</th>
					<th align="right">
						<font color="white">{1}</font>
					</th>
				</tr>
				<tr>
					<td colspan="2">{2}</td>
				</tr>\
				""".format(self.database.upper(),
				len(self.strainInfo[strainName][self.database]),
				", ".join(self.strainInfo[strainName][self.database]))

			content += """\
			<tr bgcolor="#00438A">
				<th align="left">
					<font color="white">FROZEN STOCK</font>
				</th>
				<th align="right">
					<font color="white">{0}</font>
				</th>
			</tr>
			<tr>
				<td colspan="2">{1}</td>
			</tr>\
			""".format(len(self.strainInfo[strainName]["Frozen Stock"]),
			", ".join(self.strainInfo[strainName]["Frozen Stock"]))

			content += """\
			<tr bgcolor="#00734D">
				<th align="left">
					<font color="white">DNA</font>
				</th>
				<th align="right">
					<font color="white">{0}</font>
				</th>
			</tr>
			<tr>
				<td colspan="2">{1}</td>
			</tr>\
			""".format(len(self.strainInfo[strainName]["DNA"]),
			", ".join(self.strainInfo[strainName]["DNA"]))

			content += "</table>"
		self.infoBrowser.setHtml(QString(content))

	def viewTree(self):
		"""Toolbar button/action to switch to tree view."""
		self.selectRadioButton.setChecked(True)
		if not self.populatedTree:
			self.stackedWidget.setCurrentIndex(0)
			self.refresh()
		self.stackedWidget.setCurrentIndex(0)
		self.updateUi()

	def refresh(self):
		"""Updates view(s)."""
		index = self.stackedWidget.currentIndex()
		if index == 1:
			self.populatedTable = False
			self.selectedWidget.clear()
			self.getAllSelected()
		elif index == 0:
			self.populatedTree = False
			self.treeWidget.clear()
			self.treeWidget.setDisabled(True)
			bnField = "ItemTracker ID"
			self.selectedIds = {}
			self.errorIds = {}
			selection = DB.Db.Selection
			self.selectedIds, self.errorIds = bn.getItemIds(bnField, selection)
			if len(self.selectedIds):
				self.strainInfo = {}
				self.itemIds = {}
				self.getBnFields()
#			self.populateTree()
			QTimer.singleShot(0, self.populateTree)
		elif index == 2:
			self.populatedCherry = False
			QTimer.singleShot(0, self.cherryPicking)

		self.updateUi()
Exemple #9
0
class MainWindow(QMainWindow):
	def __init__(self):
		QMainWindow.__init__(self)
		
		self.setWindowTitle('%s %s' % (QApplication.applicationName(), QApplication.applicationVersion()));

		self.config = ConfigHandler(os.path.join(os.path.expanduser('~'), '.pywv/pywv.cfg'), self)

		self.setStyle(QStyleFactory.create(self.config.loadStyle()))
		if self.config.loadStyleSheet():
			self.setStyleSheet(self.config.loadStyleSheet())
		else:
			self.setStyleSheet("* {}") # without any stylesheet, windowstyles won't apply


		self.setDockOptions(QMainWindow.AnimatedDocks | QMainWindow.AllowNestedDocks | QMainWindow.AllowTabbedDocks | QMainWindow.VerticalTabs);

#		self.dummy = QWidget(self)
		self.setCentralWidget(QWidget(self))

		self.pBar = QProgressBar(self)
		self.pBar.setRange(0, self.config.loadReloadInterval())
		self.pBar.setFormat("%v Sekunden")
		if not self.config.loadAutoload():
			self.pBar.hide()

		self.statusBar = QStatusBar(self)
		self.setStatusBar(self.statusBar)
		self.statusBar.addWidget(self.pBar)

		self.reloadTimer = QTimer(self);
		self.reloadTimer.setInterval(self.config.loadReloadInterval() * 1000)
		self.connect(self.reloadTimer, SIGNAL('timeout()'), self.reload_)
		if self.config.loadAutoload():
			self.reloadTimer.start()

		self.autoloadStatusTimer = QTimer(self)
		self.autoloadStatusTimer.setInterval(1000) # 1 sec
		self.connect(self.autoloadStatusTimer, SIGNAL('timeout()'), self.onAutoloadStatus)
		self.autoloadStatusTimer.start()

		self.mAction = self.menuBar().addMenu(self.tr("&Action"))
		self.mAction.addAction(self.tr("&update"), self.reload_, QKeySequence('F5'))
		self.mAction.addAction(self.tr("e&xit"), self.onExit, 'Ctrl+Q')

		self.mStyle = QMenu(self.tr("&Style"), self)
		for s in list(QStyleFactory.keys()):#       // fill in all available Styles
			self.mStyle.addAction(s)
		self.connect(self.mStyle, SIGNAL('triggered(QAction*)'), self.onStyleMenu)

		self.mOption = self.menuBar().addMenu(self.tr("&Options"))
		self.mOption.addAction(self.tr("reloadinterval") , self.onReloadTime , 'F8')
		self.mOption.addAction(self.tr("manage links")   , self.onNewLink    , 'F6')
		self.mOption.addSeparator()

		self.ontopAction       = QAction(self.tr("always on &top")  , self)
		self.showTrayAction    = QAction(self.tr("show tray &icon") , self)
		self.closeToTrayAction = QAction(self.tr("close to &tray")  , self)
		self.autoloadAction    = QAction(self.tr("auto&load")       , self)

		self.ontopAction.setCheckable(True)
		self.showTrayAction.setCheckable(True)
		self.closeToTrayAction.setCheckable(True)
		self.autoloadAction.setCheckable(True)

		self.showTrayAction.setChecked   (self.config.loadShowTray()   )
		self.ontopAction.setChecked      (self.config.loadOntop()      )
		self.closeToTrayAction.setChecked(self.config.loadCloseToTray())
		self.autoloadAction.setChecked   (self.config.loadAutoload()   )

		self.connect(self.ontopAction       , SIGNAL('toggled(bool)') , self.onOntopAction)
		self.connect(self.showTrayAction    , SIGNAL('toggled(bool)') , self.onShowTrayAction)
		self.connect(self.closeToTrayAction , SIGNAL('toggled(bool)') , self.onCloseToTrayAction)
		self.connect(self.autoloadAction    , SIGNAL('toggled(bool)') , self.onAutoloadAction)

		self.mOption.addAction(self.ontopAction)
		self.mOption.addAction(self.showTrayAction)
		self.mOption.addAction(self.closeToTrayAction)
		self.mOption.addAction(self.autoloadAction)
		self.mOption.addSeparator()
		self.mOption.addMenu(self.mStyle)

		self.trayIcon = QSystemTrayIcon(QIcon(':/appicon'), self);
		self.trayMgr = TrayManager(self.config, self.trayIcon)
		self.connect(self.trayIcon, SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.onTrayIcon)
		if self.config.loadShowTray(): self.trayIcon.show()

		self.trayIconMenu = QMenu()
		self.trayIconMenu.addAction(self.tr("e&xit"), self.onExit)
		self.trayIcon.setContextMenu(self.trayIconMenu)

		self.mAbout = self.menuBar().addMenu(self.tr("&about"))
		self.mAbout.addAction(QApplication.applicationName(), self.onAboutAppAction)
		self.mAbout.addAction("Qt", self.onAboutQtAction)

		self.createWidgets()

		self.resize(self.config.loadWindowSize())
		self.restoreState(self.config.loadWindowState())

		if self.config.loadIsVisible():
			self.show()
			self.reload_()

	def __del__(self):
		self.config.saveWindowState(self.saveState())

	def createSingleWidget(self, name):
#		print 'crt', name, type(name), '\n', self.widgets
#		print 'crt', name, type(name)
		links = self.config.loadLinks()
		if links[name]['type'] == 'generic':
			self.widgets[name] = GenericWidget(name, self.config, self)
		else:
			pluginsAvail = classdirPlugins().all_()
			for plugin in pluginsAvail:
				if links[name]['type'] == plugin['class']:
					pluginClass = plugin['class']
					break
				else:
					continue

			exec('self.widgets[name] = %s(name, self.config, self)' % pluginClass)
		#	print(('loaded plugin', self.widgets[name]))

		self.addDockWidget(0x4, self.widgets[name])
		self.widgets[name].reload_()

	def delWidget(self, name):
		#print 'del', name, type(name), '\n', self.widgets
		self.removeDockWidget(self.widgets[name])
		self.widgets[name].deleteLater()
		self.widgets[name] = None
		del self.widgets[name]

	def createWidgets(self):
		self.widgets = {}
		for name in self.config.loadLinks():
			self.createSingleWidget(name)


	@pyqtSlot()
	def onExit(self):
		self.config.saveWindowSize(self.size())
		QApplication.exit();

	def closeEvent(self, event):
		self.config.saveWindowSize(self.size())
#	       	QApplication.exit()
		# tray is visible -> close to tray
		# else close app
		if self.trayIcon.isVisible():
			event.accept()
		else:
			QApplication.exit()
			return
		# if close-to-tray is set, do so
		if self.config.loadCloseToTray():
			event.accept()
		else:
			QApplication.exit()
			return;
		# save this state
		if	self.trayIcon.isVisible():	self.config.saveIsVisible(False)
		else:					self.config.saveIsVisible(True);
	@pyqtSlot()
	def reload_(self):
		for name in self.widgets:
			self.widgets[name].reload_()
		self.pBar.setValue(self.config.loadReloadInterval())
		self.reloadTimer.start(self.config.loadReloadInterval()*1000)

	@pyqtSlot()
	def onAutoloadStatus(self):
		self.pBar.setValue(self.pBar.value()-1)
#		print([idx for idx in self.widgets])

	def onStyleMenu(self, a):
		QApplication.setStyle(QStyleFactory.create(a.text()))
		self.setStyle(QStyleFactory.create(a.text()))
		self.config.saveStyle(a.text())

	def onReloadTime(self):
		ok = False
		value, ok = QInputDialog.getInteger(self,
			self.tr("reloadinterval"), # title
			self.tr("insert time in s"), # text
			self.config.loadReloadInterval(), # default
			10, # minimum
			86400, # maximum (at least once a day)
			1, # step
			)
		if ok:
			self.config.saveReloadInterval(value)
			self.pBar.setRange(0,self.config.loadReloadInterval())
			self.reload_()

	def onAutoloadAction(self, b):
		if b:
			self.reloadTimer.start()
			self.pBar.show()
			self.reload_()
		else:
			self.reloadTimer.stop()
			self.pBar.hide()
		self.config.saveAutoload(b)

	def onNewLink(self):
		inp = LinkInput(self.config, self)
		if inp.exec_():
			# sync active widgets
			for name in inp.modifiedWidgets():
				if name in self.widgets:
					self.delWidget(name)
					self.createSingleWidget(name)
				else:
					self.createSingleWidget(name)

			# remove deleted
#			for name in self.widgets: print 'shown', name
#			for name in self.config.loadLinks(): print 'conf', name
			todel = []
			for name in self.widgets:
				if name not in self.config.loadLinks():
					todel.append(name)

			for widget in todel:
				self.delWidget(widget)

	def onOntopAction(self, b):
		if b:	self.setWindowFlags(Qt.Dialog | Qt.WindowStaysOnTopHint)
		else:	self.setWindowFlags(Qt.Dialog)
		self.setWindowIcon(QIcon(':/appicon'))
		self.show();
		self.config.saveOntop(b)

	def onShowTrayAction(self, b):
		if b:	self.trayIcon.show()
		else:	self.trayIcon.hide()
		self.config.saveShowTray(b)

	def onCloseToTrayAction(self, b):
		self.config.saveCloseToTray(b)

	def onTrayIcon(self, reason):
		if reason == QSystemTrayIcon.Trigger:
			if(self.isVisible()):
				self.config.saveWindowSize(self.size())
				self.hide()
				self.config.saveIsVisible(False)
			else:
				self.show()
				self.resize(self.config.loadWindowSize())
				self.config.saveIsVisible(True)

	def onAboutAppAction(self):
		QMessageBox.about(self, self.tr("&about"), self.tr("name %1 version %2").arg(QApplication.applicationName()).arg(QApplication.applicationVersion()))
	def onAboutQtAction(self):
		QMessageBox.aboutQt(self, self.tr("&about"))
Exemple #10
0
class GUI(QWidget):
    def __init__(self, parent=None):
        super(GUI, self).__init__(parent)

        self.create_ui_components()
        self.compose_ui()

        # Initializing: window composition, it's contents and event handlers
        self.init_composition()
        self.init_contents()
        self.init_actions()

        self.on_start()

    def create_ui_components(self):
        """
        Create layouts and qt controls.
        """
        self.layout = QGridLayout()

        self.kanjiGroup = QGroupBox()
        self.kanjiLayout = QGridLayout()

        # Kanji ui group
        self.day, self.week, self.month, self.year = \
        QLabel(KANJI), QLabel(KANJI), QLabel(KANJI), QLabel(KANJI)

        self.dayLabel, self.weekLabel, self.monthLabel, self.yearLabel = \
        QLabel('<b>Day</b>'), QLabel('<b>Week</b>'), \
        QLabel('<b>Month</b>'), QLabel('<b>Year</b>')

        # Main layout
        self.showAbout = QPushButton('A&bout')
        # DB controls (top)
        self.showDB, self.availableDB, self.changeDB = \
        QPushButton('&Change DB (active:)'), QComboBox(), QPushButton('&Remap')
        # General controls (bottom)
        self.getAll, self.showStats, self.quitApp, self.authGen, self.methodCombo = \
        QPushButton('&Get all'), QPushButton('&Stats'), QPushButton('&Quit'), \
        QPushButton('&Auth'), QComboBox()
        # Notifications
        self.progressBar = QProgressBar()
        self.statusMessage = QLabel()
        # About
        self.aboutBox = QMessageBox()

    def compose_ui(self):
        """
        Fill layouts and groups, initialize filters.
        """
        self.kanjiLayout.addWidget(self.day, 0, 0)
        self.kanjiLayout.addWidget(self.week, 0, 1)
        self.kanjiLayout.addWidget(self.dayLabel, 1, 0)
        self.kanjiLayout.addWidget(self.weekLabel, 1, 1)

        self.kanjiLayout.addWidget(self.month, 2, 0)
        self.kanjiLayout.addWidget(self.year, 2, 1)
        self.kanjiLayout.addWidget(self.monthLabel, 3, 0)
        self.kanjiLayout.addWidget(self.yearLabel, 3, 1)

        self.kanjiGroup.setLayout(self.kanjiLayout)

        self.layout.addWidget(self.showDB, 0, 0, 1, 2)
        self.layout.addWidget(self.availableDB, 1, 0)
        self.layout.addWidget(self.changeDB, 1, 1)
        self.layout.addWidget(self.kanjiGroup, 2, 0, 1, 2)
        self.layout.addWidget(self.getAll, 3, 0)
        self.layout.addWidget(self.showStats, 3, 1)
        self.layout.addWidget(self.methodCombo, 4, 0)
        self.layout.addWidget(self.authGen, 4, 1)
        #self.layout.addWidget(self.quitApp, 5, 0, 1, 2)
        self.layout.addWidget(self.quitApp, 5, 0)
        self.layout.addWidget(self.showAbout, 5, 1)
        self.layout.addWidget(self.progressBar, 6, 0, 1, 2)
        self.layout.addWidget(self.statusMessage, 7, 0, 1, 2)

        self.setLayout(self.layout)

        self.eFilter = LabelEventFilter()

    def on_start(self):
        """
        Additional procedures run on application start.
        """
        # Let's initialize even some stuff!
        self.al = None
        self.auth_thread = None
        self.init_backend()

        choose_db(str(self.availableDB.currentText()))
        self.showDB.setText("&Change DB (active: %s)" %
                            self.availableDB.currentText())

        self.stats = StatsUI(self.al, self)

    def init_composition(self):
        """
        Window composition and general params.
        """
        self.setWindowTitle(NAME + ' ' + __version__)
        desktop = QApplication.desktop()
        self.setGeometry((desktop.width() - WIDTH) / 2,
                         (desktop.height() - HEIGHT) / 2, WIDTH, HEIGHT)

    def init_contents(self):
        """
        Setting up qt controls.
        """
        self.changeDB.hide()
        self.availableDB.hide()
        self.availableDB.addItems(dbs.keys())

        self.kanjiGroup.setAlignment(Qt.AlignCenter)
        self.kanjiGroup.setStyleSheet(
            "QGroupBox { border: 1px solid gray; border-radius: 3px; }")

        self.day.setAlignment(Qt.AlignCenter)
        self.week.setAlignment(Qt.AlignCenter)
        self.month.setAlignment(Qt.AlignCenter)
        self.year.setAlignment(Qt.AlignCenter)
        self.dayLabel.setAlignment(Qt.AlignCenter)
        self.weekLabel.setAlignment(Qt.AlignCenter)
        self.monthLabel.setAlignment(Qt.AlignCenter)
        self.yearLabel.setAlignment(Qt.AlignCenter)

        self.day.setFont(QFont(PRETTY_FONT, KANJI_SIZE))
        self.week.setFont(QFont(PRETTY_FONT, KANJI_SIZE))
        self.month.setFont(QFont(PRETTY_FONT, KANJI_SIZE))
        self.year.setFont(QFont(PRETTY_FONT, KANJI_SIZE))

        self.methodCombo.addItems(RandomMess.algs.keys())
        self.methodCombo.setCurrentIndex(1)

        self.statusMessage.setAlignment(Qt.AlignCenter)
        self.statusMessage.hide()
        self.statusMessage.setMaximumHeight(MESSAGE_HEIGHT)
        self.statusMessage.setStyleSheet(WARNING_STYLE)

        self.progressBar.setMaximum(0)
        self.progressBar.setMaximumHeight(PROGRESS_HEIGHT)
        self.progressBar.hide()

        QToolTip.setFont(QFont(PRETTY_FONT, TOOLTIP_FONT_SIZE))

        self.getAll.setToolTip('Randomly select all 4 kanji')
        self.methodCombo.setToolTip('Choose algorithm for randomness')
        self.authGen.setToolTip('Authorize on remote RNG services')
        self.showStats.setToolTip(
            'Show/hide dialog with comprehensive statistics')
        self.quitApp.setToolTip('Close application')
        self.showDB.setToolTip('Show/hide available databases')
        self.availableDB.setToolTip('Available kanji frequency charts db')
        self.changeDB.setToolTip('Pick new kanji from currently selected db')

        # About dialog
        self.aboutBox.layout().itemAt(1).widget().setAlignment(Qt.AlignLeft)

        self.aboutBox.setTextFormat(Qt.RichText)
        self.aboutBox.setText('Version:\t<b>' + __version__ +
                              '</b><br/>Python:\t<b>' +
                              platform.python_version() + '</b>' +
                              '<br/>Platform:\t<b>' + platform.system() + ' ' +
                              platform.release() + '</b>' +
                              '<br/>Author:\t<b>' + __author__ + '</b>' +
                              app_about)
        self.aboutBox.setWindowTitle('About ' + app_name)
        self.aboutBox.setIconPixmap(QPixmap(paths['icon']))

    def init_actions(self):
        """
        Binding events/handlers.
        """
        self.showDB.clicked.connect(self.show_available_db)
        self.changeDB.clicked.connect(self.change_db)

        self.quitApp.clicked.connect(self.close)
        self.getAll.clicked.connect(self.get_all)
        self.authGen.clicked.connect(self.auth_task)
        self.showStats.clicked.connect(self.show_stats)
        self.methodCombo.currentIndexChanged.connect(self.update_alg)

        self.showAbout.clicked.connect(self.app_help)

        # Mouse events for labels
        self.day.setAttribute(Qt.WA_Hover, True)
        self.week.setAttribute(Qt.WA_Hover, True)
        self.month.setAttribute(Qt.WA_Hover, True)
        self.year.setAttribute(Qt.WA_Hover, True)
        self.day.installEventFilter(self.eFilter)
        self.week.installEventFilter(self.eFilter)
        self.month.installEventFilter(self.eFilter)
        self.year.installEventFilter(self.eFilter)

    ##### actions #####

    def show_stats(self):
        if self.stats.isVisible():
            self.stats.hide()
        else:
            self.stats.show()

    def show_available_db(self):
        if self.availableDB.isVisible():
            self.availableDB.hide()
            self.changeDB.hide()
        else:
            self.availableDB.show()
            self.changeDB.show()

    def change_db(self):
        try:
            choose_db(str(self.availableDB.currentText()))
            self.availableDB.hide()
            self.changeDB.hide()
            self.show_message_then_hide("DB successfully remaped!", False)
            self.showDB.setText("&Change DB (active: %s)" %
                                self.availableDB.currentText())

            self.stats.update_stat_info()
            self.stats.refresh_plot()
        except NoDbException as e:
            self.show_message_then_hide(e.message)

    def get_all(self):
        self.random_kanji_task = RandomKanjiTask(self.al)
        self.random_kanji_task.done.connect(self.update_kanji)
        self.show_progress('Selecting kanji...')
        self.random_kanji_task.start()

    def update_kanji(self, results):
        if results['success']:
            kanji_set = results['kanji_set']
            for_a_day = kanji_set.pop()
            for_a_week = kanji_set.pop()
            for_a_month = kanji_set.pop()
            for_a_year = kanji_set.pop()

            self.day.setText(for_a_day.character)
            self.dayLabel.setText('<b>Day:</b> ' + str(for_a_day.frequency) +
                                  ' | ' + str(for_a_day.dominance) + '%')
            self.week.setText(for_a_week.character)
            self.weekLabel.setText('<b>Week:</b> ' +
                                   str(for_a_week.frequency) + ' | ' +
                                   str(for_a_week.dominance) + '%')
            self.month.setText(for_a_month.character)
            self.monthLabel.setText('<b>Month:</b> ' +
                                    str(for_a_month.frequency) + ' | ' +
                                    str(for_a_month.dominance) + '%')
            self.year.setText(for_a_year.character)
            self.yearLabel.setText('<b>Year:</b> ' +
                                   str(for_a_year.frequency) + ' | ' +
                                   str(for_a_year.dominance) + '%')

            self.kanji_tooltip(self.day)
            self.kanji_tooltip(self.week)
            self.kanji_tooltip(self.month)
            self.kanji_tooltip(self.year)

            if self.stats.isVisible():
                self.stats.update_stat_info()
                self.stats.refresh_plot()

            self.hide_message()
        else:
            self.show_message_then_hide(results['message'])

        self.hide_progress()

    def pretty_font(self):
        pass

    def update_alg(self):
        self.al.set_active(str(self.methodCombo.currentText()))

    def init_backend(self):
        self.al = RandomMess()
        self.update_alg()

    def auth_task(self):
        self.auth_thread = AuthorizationTask(self.al)
        self.auth_thread.done.connect(self.auth_complete)
        #self.auth_thread.run()
        # IT DOESN't work on windows as it should!
        self.auth_thread.start()
        self.show_progress('Authorizing on RNG services...')

    def auth_complete(self, success):
        self.hide_message()
        self.hide_progress()
        if success:
            self.show_message_then_hide("Successfully authenticated!", False)
        else:
            self.show_message_then_hide("Sorry, could not authenticate.")

    def show_message_then_hide(self, message, error=True):
        if error:
            self.statusMessage.setStyleSheet(WARNING_STYLE)
        else:
            self.statusMessage.setStyleSheet(NOTE_STYLE)

        self.statusMessage.setText(message)
        self.statusMessage.show()
        QTimer.singleShot(MESSAGE_TIMEOUT, self.hide_message)

    def show_progress(self, message):
        self.statusMessage.setStyleSheet(NOTE_STYLE)
        self.statusMessage.setText(message)
        self.statusMessage.show()
        self.progressBar.show()

    def hide_message(self):
        self.statusMessage.setText('')
        self.statusMessage.hide()

    def hide_progress(self):
        self.progressBar.hide()

    def toggle_kanji_info(self, label, info):
        label.setToolTip(info.info())

    def kanji_tooltip(self, label):
        found = JDIC.search(label.text())
        if found:
            label.setToolTip(found.info())
        else:
            label.setToolTip('No such kanji in kanjidic2!')

    def kanji_info(self, kanji):
        pass

    def app_help(self):
        self.aboutBox.show()

        #### Utility events ####

    def resizeEvent(self, QResizeEvent):
        self.updateStatsPosition()
        self.updateStatsSize()

    def moveEvent(self, QMoveEvent):
        self.updateStatsPosition()
        self.updateStatsSize()

    def updateStatsPosition(self):
        self.stats.move(self.x() + self.width() + 20, self.y())

    def updateStatsSize(self):
        self.stats.resize(QSize(self.stats.width(), self.height()))
Exemple #11
0
class FeedLol(QMainWindow):
    def __init__(self, parent = None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("FeedLol")
        
        self.aboutAction = QAction(QIcon("data/icons/help-about.svg"), "&About FeedLol...", self)
        self.connect(self.aboutAction, SIGNAL("triggered()"), self.slotAbout)
        
        self.reloadAction = QAction(QIcon("data/icons/view-refresh.svg"), "&Reload", self)
        self.reloadAction.setShortcut(QKeySequence.Refresh)
        
        self.homeAction = QAction(QIcon("data/icons/go-home.svg"), "Go &Home", self)
        self.homeAction.setShortcut("Alt+Home")
        
        self.userAction = QAction(QIcon("data/icons/user-identity.svg"), "&Me", self)
        self.userAction.setShortcut("Ctrl+M")
        
        self.logoutAction = QAction(QIcon("data/icons/dialog-close.svg"), "Log&out", self)
        self.logoutAction.setShortcut(QKeySequence.Close)
        
        self.settingsAction = QAction(QIcon("data/icons/configure.svg"), "&Preferences...", self)
        self.connect(self.settingsAction, SIGNAL("triggered()"), self.slotSettings)

        self.toolbar = QToolBar("Toolbar", self)
        self.toolbar.setObjectName("toolbar")
        self.toolbar.addAction(self.homeAction)
        self.toolbar.addAction(self.userAction)
        self.toolbar.addAction(self.reloadAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.logoutAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.settingsAction)
        self.toolbar.addAction(self.aboutAction)
        self.addToolBar(self.toolbar)
        
        self.loadStatus = QProgressBar(self)
        self.loadStatus.setRange(0, 100)
        self.loadStatus.setMaximumWidth(200)
        self.loadStatus.setTextVisible(False)
        self.loadStatus.hide()
        self.statusBar().addPermanentWidget(self.loadStatus)

        self.feedView = FeedView(self)
        self.setCentralWidget(self.feedView)
        self.connect(self.feedView, SIGNAL("titleChanged(const QString&)"), self.slotSetTitle)
        self.connect(self.feedView, SIGNAL("statusBarMessage(const QString&)"), self.statusBar(), SLOT("showMessage(const QString&)"))
        self.connect(self.feedView, SIGNAL("loadStarted()"), self.loadStart)
        self.connect(self.feedView, SIGNAL("loadFinished(bool)"), self.loadStop)
        self.connect(self.feedView, SIGNAL("loadProgress(int)"), self.loadProgress)
        self.connect(self.reloadAction, SIGNAL("triggered()"), self.feedView.reload)
        self.connect(self.homeAction, SIGNAL("triggered()"), self.feedView.goHome)
        self.connect(self.userAction, SIGNAL("triggered()"), self.feedView.goToUserPage)
        self.connect(self.logoutAction, SIGNAL("triggered()"), self.feedView.logout)
        self.connect(self.feedView.page(), SIGNAL("linkHovered(const QString&, const QString&, const QString&)"), self.linkHovered)
        
        self.settingsDialog = SettingsDialog(self.feedView, self)

        settings = QSettings()
        
        if settings.contains("proxy/type"):
            proxy = QNetworkProxy()
            proxyType = settings.value("proxy/type").toInt()[0]
            proxy.setType( (proxyType == 2) and QNetworkProxy.Socks5Proxy or ( (proxyType == 1) and QNetworkProxy.HttpProxy or QNetworkProxy.NoProxy ) )
            if proxy.type() != QNetworkProxy.NoProxy:
                proxy.setHostName(settings.value("proxy/host").toString())
                proxy.setPort(settings.value("proxy/port").toInt()[0])
                if settings.value("proxy/user").toString():
                    proxy.setUser(settings.value("proxy/user").toString())
                    proxy.setPassword(settings.value("proxy/password").toString())
            QNetworkProxy.setApplicationProxy(proxy)

        if settings.contains("mainWindow/geometry"):
            self.restoreGeometry(settings.value("mainWindow/geometry").toByteArray())
        else:
            self.resize(320,480)
        if settings.contains("mainWindow/state"):
            self.restoreState(settings.value("mainWindow/state").toByteArray())
        
        self.feedView.goHome()
        
    def saveConfig(self):
        settings = QSettings()
        settings.setValue("mainWindow/geometry", QVariant(self.saveGeometry()))
        settings.setValue("mainWindow/state", QVariant(self.saveState()))
        session = self.feedView.siteServer.session
        from cPickle import dumps
        session = dumps(session)
        settings.setValue("session", QVariant(session))
        proxy = QNetworkProxy.applicationProxy()
        proxyType = (proxy.type() == QNetworkProxy.Socks5Proxy) and 2 or ( (proxy.type() == QNetworkProxy.HttpProxy) and 1 or 0 )
        settings.setValue("proxy/type", QVariant(proxyType))
        settings.setValue("proxy/host", QVariant(proxy.hostName()))
        settings.setValue("proxy/port", QVariant(proxy.port()))
        settings.setValue("proxy/user", QVariant(proxy.user()))
        settings.setValue("proxy/password", QVariant(proxy.password()))

    def slotAbout(self):
        from PyQt4.QtGui import QMessageBox
        QMessageBox.about(self, "FeedLol", "<h2>FeedLol 0.1</h2><p>Copyright &copy; 2008 <a href=\"mailto:[email protected]\">Bodil Stokke</a></p>")
        
    def slotSettings(self):
        self.settingsDialog.updateSettings()
        if self.settingsDialog.exec_() == QDialog.Accepted:
            self.settingsDialog.applySettings()

    def slotSetTitle(self, title):
        self.setWindowTitle("FeedLol: " + title)
        
    def loadStart(self):
        self.loadStatus.show()
    
    def loadStop(self):
        self.loadStatus.hide()
        
    def loadProgress(self, progress):
        self.loadStatus.setValue(progress)
    
    def linkHovered(self, url, title, text):
        if url and QUrl(url).scheme() != "chrome":
            self.statusBar().showMessage(url)
        else:
            self.statusBar().clearMessage()
Exemple #12
0
class BrowserWindow(QMainWindow):
    def retranslateUi(self):
        self.setWindowTitle(
            QApplication.translate("self", "self", None,
                                   QApplication.UnicodeUTF8))
        self.menuFile.setTitle(
            QApplication.translate("self", "&File", None,
                                   QApplication.UnicodeUTF8))
        self.menuView.setTitle(
            QApplication.translate("self", "&View", None,
                                   QApplication.UnicodeUTF8))
        self.menuEdit.setTitle(
            QApplication.translate("self", "&Edit", None,
                                   QApplication.UnicodeUTF8))
        self.menuHelp.setTitle(
            QApplication.translate("self", "&Help", None,
                                   QApplication.UnicodeUTF8))
        self.toolBar.setWindowTitle(
            QApplication.translate("self", "toolBar", None,
                                   QApplication.UnicodeUTF8))
        self.actionHome.setText(
            QApplication.translate("self", "&Home", None,
                                   QApplication.UnicodeUTF8))
        self.actionHome.setToolTip(
            QApplication.translate("self", "Go Home", None,
                                   QApplication.UnicodeUTF8))
        self.actionShowMenu.setText(
            QApplication.translate("self", "Show &Menu", None,
                                   QApplication.UnicodeUTF8))
        self.actionShowToolbar.setText(
            QApplication.translate("self", "Show &Toolbar", None,
                                   QApplication.UnicodeUTF8))
        self.actionClose.setText(
            QApplication.translate("self", "&Close", None,
                                   QApplication.UnicodeUTF8))
        self.actionModifyWebapp.setText(
            QApplication.translate("self", "Modify &Webapp", None,
                                   QApplication.UnicodeUTF8))
        self.actionEditPreferences.setText(
            QApplication.translate("self", "Edit &Preferences", None,
                                   QApplication.UnicodeUTF8))
        self.actionPrint.setText(
            QApplication.translate("self", "&Print", None,
                                   QApplication.UnicodeUTF8))
        self.actionAbout.setText(
            QApplication.translate("self", "&About", None,
                                   QApplication.UnicodeUTF8))

    def __init__(self, appid, base, name):
        super(BrowserWindow, self).__init__()

        self.appid = appid
        self.name = name
        self.original_name = name
        self.base = base

        # Main widgets
        self.centralwidget = QWidget(self)
        self.gridLayout_2 = QGridLayout(self.centralwidget)
        self.setCentralWidget(self.centralwidget)
        self.urlLineEdit = QLineEdit(self)
        self.progressBar = QProgressBar(self)

        # Custom webview
        self.page = LocalWebPage()
        self.page.setFeaturePermission(self.page.mainFrame(),
                                       LocalWebPage.Notifications,
                                       LocalWebPage.PermissionGrantedByUser)
        self.webkitNotifications = WebkitNotifications(self)

        self.webViewMain = LocalWebView(self.centralwidget)
        self.webViewMain.setPage(self.page)
        self.gridLayout_2.addWidget(self.webViewMain, 0, 0, 1, 1)

        self.webViewMain.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)

        self.menubar = QMenuBar(self)
        self.menuFile = QMenu(self.menubar)
        self.menuView = QMenu(self.menubar)
        self.menuEdit = QMenu(self.menubar)
        self.menuHelp = QMenu(self.menubar)
        self.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(self)
        self.setStatusBar(self.statusbar)
        self.toolBar = QToolBar(self)
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        self.addToolBar(Qt.TopToolBarArea, self.toolBar)

        # Create actions
        self.actionOpenLinkInNewWindow = self.page.action(
            self.page.OpenLinkInNewWindow)
        self.actionOpenLinkInNewWindow.setText(
            tr('BrowserWindow', 'Open in &Browser'))
        self.actionBack = self.page.action(self.page.Back)
        self.actionForward = self.page.action(self.page.Forward)
        self.actionStop = self.page.action(self.page.Stop)
        self.actionReload = self.page.action(self.page.Reload)
        self.actionHome = QAction(self)
        self.actionShowMenu = QAction(self)
        self.actionShowMenu.setCheckable(True)
        self.actionShowToolbar = QAction(self)
        self.actionShowToolbar.setCheckable(True)
        self.actionClose = QAction(self)
        self.actionModifyWebapp = QAction(self)
        self.actionEditPreferences = QAction(self)
        self.actionPrint = QAction(self)
        self.actionSaveLink = self.page.action(self.page.DownloadLinkToDisk)
        self.actionSaveLink.setEnabled(False)
        self.actionAbout = QAction(self)

        # Populate menu and toolbars
        self.menuFile.addAction(self.actionHome)
        self.menuFile.addAction(self.actionBack)
        self.menuFile.addAction(self.actionForward)
        self.menuFile.addAction(self.actionStop)
        self.menuFile.addAction(self.actionReload)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.actionPrint)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.actionClose)
        self.menuView.addAction(self.actionShowMenu)
        self.menuView.addAction(self.actionShowToolbar)
        self.menuView.addSeparator()
        self.menuEdit.addAction(self.actionModifyWebapp)
        #self.menuEdit.addAction(self.actionEditPreferences)
        self.menuHelp.addAction(self.actionAbout)
        self.menubar.addAction(self.menuFile.menuAction())
        self.menubar.addAction(self.menuEdit.menuAction())
        self.menubar.addAction(self.menuView.menuAction())
        self.menubar.addAction(self.menuHelp.menuAction())
        self.toolBar.addAction(self.actionHome)
        self.toolBar.addAction(self.actionBack)
        self.toolBar.addAction(self.actionForward)
        self.toolBar.addWidget(self.urlLineEdit)

        self.toolBar.addAction(self.actionStop)
        self.toolBar.addAction(self.actionReload)

        self.retranslateUi()
        QMetaObject.connectSlotsByName(self)

        self.setWindowTitle(self.name)

        # Set up cookie jar that persists sessions
        self.cookieJar = PersistableCookieJar(self, identifier=self.appid)
        self.cookieJar.load()
        self.webViewMain.page().networkAccessManager().setCookieJar(
            self.cookieJar)

        # Set up link delegation so that external links open in web browser.
        self.webViewMain.page().setLinkDelegationPolicy(
            QWebPage.DelegateExternalLinks)

        self.desktopEntry = desktop.getEntry(self.appid)

        # Set icons for actions; this can't be done in the designer, AFAICT
        self.actionHome.setIcon(QIcon.fromTheme('go-home'))
        self.actionAbout.setIcon(QIcon.fromTheme('help-about'))

        # Set up shortcuts
        self.actionStop.setShortcut(Qt.Key_Escape)
        self.actionBack.setShortcut(QKeySequence.Back)
        self.actionForward.setShortcut(QKeySequence.Forward)
        self.actionReload.setShortcut(QKeySequence.Refresh)
        self.actionHome.setShortcut('Ctrl+Home')
        self.actionShowMenu.setShortcut('Ctrl+m')
        self.actionShowToolbar.setShortcut('Ctrl+t')
        self.actionPrint.setShortcut(QKeySequence.Print)

        self.backShortcut = QShortcut(self)
        self.backShortcut.setKey(Qt.Key_Back)
        self.backShortcut.activated.connect(self.webViewMain.back)

        self.forwardShortcut = QShortcut(self)
        self.forwardShortcut.setKey(Qt.Key_Forward)
        self.forwardShortcut.activated.connect(self.webViewMain.forward)

        # Set up context menu
        self.webViewMain.setContextMenuPolicy(Qt.CustomContextMenu)
        self.webViewMain.customContextMenuRequested.connect(self.showMenu)

        # Setup statusbar and toolbar
        for c in self.statusBar().children()[0].children():
            c.removeWidget(c)
        self.statusBar().addPermanentWidget(self.progressBar, 1)

        self.actionShowToolbar.setChecked(True)
        self.actionShowMenu.setChecked(True)

        # Icon
        if self.desktopEntry.hasKey('Icon'):
            self.icon = QIcon(self.desktopEntry.get('Icon'))
            self.setWindowIcon(self.icon)
        else:
            self.webViewMain.iconChanged.connect(self.setWindowIcon)

        # Set up events
        if self.desktopEntry.get('X-%s-menu-enabled' % APP_NAME) == '0':
            self.actionShowMenu.setChecked(False)
        else:
            self.actionShowMenu.setChecked(True)
        if self.desktopEntry.get('X-%s-toolbar-enabled' % APP_NAME) == '0':
            self.actionShowToolbar.setChecked(False)
        else:
            self.actionShowToolbar.setChecked(True)

        self.webViewMain.linkClicked.connect(self._onLinkClick)
        self.webViewMain.titleChanged.connect(self.setWindowTitle)
        self.webViewMain.loadProgress.connect(self._setLoadingStatus)
        self.webViewMain.urlChanged.connect(
            lambda x: self.urlLineEdit.setText(x.toString()))
        self.page.printRequested.connect(self._onPrint)
        self.page.loadFinished.connect(self._loadingFinished)
        self.actionHome.triggered.connect(
            lambda x: self.webViewMain.load(QUrl(self.base)))
        self.actionClose.triggered.connect(self.close)
        self.actionPrint.triggered.connect(self._onPrint)
        self.urlLineEdit.returnPressed.connect(self._onUrlEdit)
        self.actionShowToolbar.triggered.connect(self._onShowToolbar)
        self.actionShowMenu.triggered.connect(self._onShowMenu)
        self.actionAbout.triggered.connect(lambda x: about.show(self))
        self.actionModifyWebapp.triggered.connect(self._onModify)

        self._onShowMenu()
        self._onShowToolbar()

        try:
            self.resize(int(self.desktopEntry.getWindowWidth()),
                        int(self.desktopEntry.getWindowHeight()))
        except (ValueError, TypeError):
            self.resize(800, 600)

        # Load first page
        self.webViewMain.load(QUrl(base))

        self.editor = SiteEditorWindow(self.desktopEntry, isNew=False)

    def _onModify(self):
        self.editor.show()

    def closeEvent(self, qCloseEvent):
        self.desktopEntry.setWindowWidth(self.width())
        self.desktopEntry.setWindowHeight(self.height())
        self.desktopEntry.write()

    def _onPrint(self):
        printer = QPrinter()
        dialog = QPrintDialog(printer, self)
        if dialog.exec_() != QDialog.Accepted:
            return
        self.page.mainFrame().print_(printer)

    def _loadingFinished(self):
        # TODO: Add user scripts here
        # TODO: Add user styles here

        # Override window.webkitNotifications
        self.page.mainFrame().addToJavaScriptWindowObject(
            "_x_webplier_webkitNotifications", self.webkitNotifications)
        self.page.mainFrame().evaluateJavaScript(
            WebkitNotifications.JAVASCRIPT)

    def _setLoadingStatus(self, value):
        if value < 100:
            self.progressBar.setValue(value)
            self.progressBar.show()
            self.statusBar().show()
            self.actionReload.setVisible(False)
            self.actionStop.setVisible(True)
        else:
            self.page.setFeaturePermission(
                self.page.mainFrame(), LocalWebPage.Notifications,
                LocalWebPage.PermissionGrantedByUser)
            self.progressBar.hide()
            self.statusBar().hide()
            self.actionReload.setVisible(True)
            self.actionStop.setVisible(False)

    def _onUrlEdit(self):
        url = unicode(self.urlLineEdit.text())
        qurl = QUrl(url)
        if not qurl.scheme():
            qurl.setScheme('http')

        self.webViewMain.load(qurl)

    def _onLinkClick(self, qurl):
        url = unicode(qurl.toString())
        if not unicode(url).startswith(self.base):
            webbrowser.open(url, 1)
        else:
            self.webViewMain.load(qurl)

    def _onShowToolbar(self):
        if self.actionShowToolbar.isChecked():
            self.toolBar.show()
            self.desktopEntry.set('X-%s-toolbar-enabled' % APP_NAME, '1')
        else:
            self.toolBar.hide()
            self.desktopEntry.set('X-%s-toolbar-enabled' % APP_NAME, '0')

    def _onShowMenu(self):
        if self.actionShowMenu.isChecked():
            self.menubar.show()
            self.desktopEntry.set('X-%s-menu-enabled' % APP_NAME, '1')
        else:
            self.menubar.hide()
            self.desktopEntry.set('X-%s-menu-enabled' % APP_NAME, '0')

    def showMenu(self, point):
        m = self.webViewMain.page().createStandardContextMenu()

        # TODO: Make this less awful and fragile
        for a in m.actions():
            if a == self.actionSaveLink:
                m.removeAction(a)

        m.addSeparator()
        m.addAction(self.actionShowMenu)
        m.addAction(self.actionShowToolbar)
        globalpos = self.mapToParent(point)

        m.exec_(globalpos)
Exemple #13
0
class Entity(QWidget):

    def __init__(self, base_image, size, hp=100, pos=(0, 0), parent=None):
        super().__init__(parent)
        self._base_label = QLabel(self)
        self._base_image = base_image
        self._size = size
        self._decor_label = None
        self._decor_pixmap = None
        self._hp_max = hp

        self.__pixmap = None
        """:type: PyQt4.QtGui.QPixmap"""

        self.__cord_x = pos[0]
        self.__cord_y = pos[1]
        self.__angle = 0

        self.__hp_bar = QProgressBar(self)
        self.__hp_bar.setMaximum(self._hp_max)
        self.__hp_bar.setValue(self._hp_max)
        self.__hp_bar.setTextVisible(False)
        self.__hp_bar.setMaximumSize(size[0], 5)

        self.setAlignment(Qt.AlignCenter)
        self.updatePixmap()

        if _debugging:
            self.setStyleSheet("border: 1px solid black")

    @property
    def health(self):
        return self.__hp_bar.value()

    @health.setter
    def health(self, hp):
        if hp > self._hp_max:
            hp = self._hp_max
        elif hp < 0:
            hp = 0
        self.__hp_bar.setValue(hp)

    @property
    def angle(self):
        return self.__angle

    @angle.setter
    def angle(self, angle):
        self.__angle = angle
        self.updatePixmap()

    @property
    def cord_x(self):
        return self.__cord_x

    @cord_x.setter
    def cord_x(self, cord):
        self.__cord_x = cord
        self.move(self.cord_x, self.cord_y)

    @property
    def cord_y(self):
        return self.__cord_y

    @cord_y.setter
    def cord_y(self, cord):
        self.__cord_y = cord
        self.move(self.cord_x, self.cord_y)

    def hide_hp_bar(self, bool=False):
        if bool:
            self.__hp_bar.hide()
        else:
            self.__hp_bar.show()

    def add_decoration(self, path):
        if path is None:
            self._decor_label.deleteLater()
            self._decor_label = None
        else:
            self._decor_label = QLabel(self)
            self._decor_pixmap = QPixmap(path)
            # self._decor_pixmap = self._decor_pixmap.scaled(self._size[0], self._size[1])
            self._decor_pixmap = self._decor_pixmap.transformed(QTransform().rotate(self.angle))
            self._decor_label.setPixmap(self._decor_pixmap)
            self._decor_label.setAlignment(Qt.AlignCenter)
            self._decor_label.show()

    def updatePixmap(self):
        path = get_asset_path(self._base_image)
        self.__pixmap = QPixmap(path)
        self.__pixmap = self.__pixmap.scaled(self._size[0], self._size[1])
        self.__pixmap = self.__pixmap.transformed(QTransform().rotate(self.angle))
        self._base_label.setPixmap(self.__pixmap)
        self._base_label.show()
        # self.setFixedSize(self.__pixmap.width(), self.__pixmap.height())

    def setFixedSize(self, x, y):
        super().setFixedSize(x, y)
        self._base_label.setFixedSize(x, y)

    def setAlignment(self, alignment):
        self._base_label.setAlignment(alignment)
Exemple #14
0
class LabelAssistDialog(QDialog):
    """
    A simple UI for showing bookmarks and navigating to them.

    FIXME: For now, this window is tied to a particular lane.
           If your project has more than one lane, then each one
           will have it's own bookmark window, which is kinda dumb.
    """
    def __init__(self, parent, topLevelOperatorView):
        super(LabelAssistDialog, self).__init__(parent)

        # Create thread router to populate table on main thread
        self.threadRouter = ThreadRouter(self)

        # Set object classification operator view
        self.topLevelOperatorView = topLevelOperatorView

        self.setWindowTitle("Label Assist")
        self.setMinimumWidth(500)
        self.setMinimumHeight(700)

        layout = QGridLayout()
        layout.setContentsMargins(10, 10, 10, 10)

        # Show variable importance table
        rows = 0
        columns = 4
        self.table = QTableWidget(rows, columns)
        self.table.setHorizontalHeaderLabels(
            ['Frame', 'Max Area', 'Min Area', 'Labels'])
        self.table.verticalHeader().setVisible(False)

        # Select full row on-click and call capture double click
        self.table.setSelectionBehavior(QTableView.SelectRows)
        self.table.doubleClicked.connect(self._captureDoubleClick)

        layout.addWidget(self.table, 1, 0, 3, 2)

        # Create progress bar
        self.progressBar = QProgressBar()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.hide()
        layout.addWidget(self.progressBar, 4, 0, 1, 2)

        # Create button to populate table
        self.computeButton = QPushButton('Compute object info')
        self.computeButton.clicked.connect(self._triggerTableUpdate)
        layout.addWidget(self.computeButton, 5, 0)

        # Create close button
        closeButton = QPushButton('Close')
        closeButton.clicked.connect(self.close)
        layout.addWidget(closeButton, 5, 1)

        # Set dialog layout
        self.setLayout(layout)

    def _triggerTableUpdate(self):
        # Check that object area is included in selected features
        featureNames = self.topLevelOperatorView.SelectedFeatures.value

        if 'Standard Object Features' not in featureNames or 'Count' not in featureNames[
                'Standard Object Features']:
            box = QMessageBox(
                QMessageBox.Warning, 'Warning',
                'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"',
                QMessageBox.NoButton, self)
            box.show()
            return

        # Clear table
        self.table.clearContents()
        self.table.setRowCount(0)
        self.table.setSortingEnabled(False)
        self.progressBar.show()
        self.computeButton.setEnabled(False)

        # Compute object features and number of labels per frame
        def compute_features():
            features = self.topLevelOperatorView.ObjectFeatures([]).wait()
            labels = self.topLevelOperatorView.LabelInputs([]).wait()
            return features, labels

        req = Request(compute_features)
        req.notify_finished(self._populateTable)
        req.submit()

    @threadRouted
    def _populateTable(self, features_and_labels):
        features, labels = features_and_labels
        self.progressBar.hide()
        self.computeButton.setEnabled(True)

        for frame, objectFeatures in features.iteritems():
            # Insert row
            rowNum = self.table.rowCount()
            self.table.insertRow(self.table.rowCount())

            # Get max and min object areas
            areas = objectFeatures['Standard Object Features']['Count']
            maxObjArea = numpy.max(areas[numpy.nonzero(areas)])
            minObjArea = numpy.min(areas[numpy.nonzero(areas)])

            # Get number of labeled objects
            labelNum = numpy.count_nonzero(labels[frame])

            # Load fram number
            item = QTableWidgetItem(str(frame))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 0, item)

            # Load max object areas
            item = QTableWidgetItemWithFloatSorting(
                str("{: .02f}".format(maxObjArea)))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 1, item)

            # Load min object areas
            item = QTableWidgetItemWithFloatSorting(
                str("{: .02f}".format(minObjArea)))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 2, item)

            # Load label numbers
            item = QTableWidgetItemWithFloatSorting(
                str("{: .01f}".format(labelNum)))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 3, item)

        # Resize column size to fit dialog size
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)

        # Sort by max object area
        self.table.setSortingEnabled(True)
        self.table.sortByColumn(1)

    def _captureDoubleClick(self):
        # Navigate to selected frame
        index = self.table.selectedIndexes()[0]
        frameStr = self.table.model().data(index).toString()

        if frameStr:
            frameNum = int(frameStr)
            self.parent().editor.posModel.time = frameNum
Exemple #15
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        
        self.home_url = None
        
        self.webview = WebView(self)
        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
                     self.load_finished)
        self.connect(self.webview, SIGNAL("titleChanged(QString)"),
                     self.setWindowTitle)
        self.connect(self.webview, SIGNAL("urlChanged(QUrl)"),
                     self.url_changed)
                
        home_button = create_toolbutton(self, icon=get_icon('home.png'),
                                        tip=_("Home"),
                                        triggered=self.go_home)
        
        zoom_out_button = action2button(self.webview.zoom_out_action)
        zoom_in_button = action2button(self.webview.zoom_in_action)
        
        pageact2btn = lambda prop: action2button(self.webview.pageAction(prop),
                                                 parent=self.webview)
        refresh_button = pageact2btn(QWebPage.Reload)
        stop_button = pageact2btn(QWebPage.Stop)
        previous_button = pageact2btn(QWebPage.Back)
        next_button = pageact2btn(QWebPage.Forward)
        
        stop_button.setEnabled(False)
        self.connect(self.webview, SIGNAL("loadStarted()"),
                     lambda: stop_button.setEnabled(True))
        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
                     lambda: stop_button.setEnabled(False))
        
        progressbar = QProgressBar(self)
        progressbar.setTextVisible(False)
        progressbar.hide()
        self.connect(self.webview, SIGNAL("loadStarted()"), progressbar.show)
        self.connect(self.webview, SIGNAL("loadProgress(int)"),
                     progressbar.setValue)
        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
                     lambda _state: progressbar.hide())
        
        label = QLabel(self.get_label())
        
        self.url_combo = UrlComboBox(self)
        self.connect(self.url_combo, SIGNAL('valid(bool)'),
                     self.url_combo_activated)
        self.connect(self.webview, SIGNAL("iconChanged()"), self.icon_changed)
        
        self.find_widget = FindReplace(self)
        self.find_widget.set_editor(self.webview)
        self.find_widget.hide()

        find_button = create_toolbutton(self, icon='find.png',
                                        tip=_("Find text"),
                                        toggled=self.toggle_find_widget)
        self.connect(self.find_widget, SIGNAL("visibility_changed(bool)"),
                     find_button.setChecked)

        hlayout = QHBoxLayout()
        for widget in (previous_button, next_button, home_button, find_button,
                       label, self.url_combo, zoom_out_button, zoom_in_button,
                       refresh_button, progressbar, stop_button):
            hlayout.addWidget(widget)
        
        layout = QVBoxLayout()
        layout.addLayout(hlayout)
        layout.addWidget(self.webview)
        layout.addWidget(self.find_widget)
        self.setLayout(layout)
Exemple #16
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.home_url = None

        self.webview = WebView(self)
        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
                     self.load_finished)
        self.connect(self.webview, SIGNAL("titleChanged(QString)"),
                     self.setWindowTitle)
        self.connect(self.webview, SIGNAL("urlChanged(QUrl)"),
                     self.url_changed)

        home_button = create_toolbutton(self,
                                        icon=get_icon('home.png'),
                                        tip=_("Home"),
                                        triggered=self.go_home)

        zoom_out_button = action2button(self.webview.zoom_out_action)
        zoom_in_button = action2button(self.webview.zoom_in_action)

        pageact2btn = lambda prop: action2button(self.webview.pageAction(prop),
                                                 parent=self.webview)
        refresh_button = pageact2btn(QWebPage.Reload)
        stop_button = pageact2btn(QWebPage.Stop)
        previous_button = pageact2btn(QWebPage.Back)
        next_button = pageact2btn(QWebPage.Forward)

        stop_button.setEnabled(False)
        self.connect(self.webview, SIGNAL("loadStarted()"),
                     lambda: stop_button.setEnabled(True))
        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
                     lambda: stop_button.setEnabled(False))

        progressbar = QProgressBar(self)
        progressbar.setTextVisible(False)
        progressbar.hide()
        self.connect(self.webview, SIGNAL("loadStarted()"), progressbar.show)
        self.connect(self.webview, SIGNAL("loadProgress(int)"),
                     progressbar.setValue)
        self.connect(self.webview, SIGNAL("loadFinished(bool)"),
                     lambda _state: progressbar.hide())

        label = QLabel(self.get_label())

        self.url_combo = UrlComboBox(self)
        self.connect(self.url_combo, SIGNAL('valid(bool)'),
                     self.url_combo_activated)
        self.connect(self.webview, SIGNAL("iconChanged()"), self.icon_changed)

        self.find_widget = FindReplace(self)
        self.find_widget.set_editor(self.webview)
        self.find_widget.hide()

        find_button = create_toolbutton(self,
                                        icon='find.png',
                                        tip=_("Find text"),
                                        toggled=self.toggle_find_widget)
        self.connect(self.find_widget, SIGNAL("visibility_changed(bool)"),
                     find_button.setChecked)

        hlayout = QHBoxLayout()
        for widget in (previous_button, next_button, home_button, find_button,
                       label, self.url_combo, zoom_out_button, zoom_in_button,
                       refresh_button, progressbar, stop_button):
            hlayout.addWidget(widget)

        layout = QVBoxLayout()
        layout.addLayout(hlayout)
        layout.addWidget(self.webview)
        layout.addWidget(self.find_widget)
        self.setLayout(layout)
Exemple #17
0
class Base(QMainWindow):
    """
    Esta clase sirve de base para todos aquellos 
    formularios que siguen el estandar de dos pestañas, una para navegación
    y otra para edición
    """

    orientation = QPrinter.Portrait
    pageSize = QPrinter.Letter
    web = ""

    def __init__(self, parent, own_toolbar=False):
        """
        @param parent: El widget padre de esta ventana
        @param own_toolbar: Si este widget dibujara su toolbar en el padre o en el mismo
        @type parent: QWidget
        @type own_toolbar: bool
        """
        super(Base, self).__init__(parent)
        self.user = user.LoggedUser
        self._status = True
        self.parentWindow = parent
        self.own_toolbar = own_toolbar

        self.database = QSqlDatabase.database()
        """
        @type: QSqlDatabase
        @ivar: La base de datos a la cual se conecta el sistema
        """

        self.mapper = QDataWidgetMapper(self)
        u"""
        @type: QDataWidgetMapper
        @ivar: El mapper que se encarga de asignar los 
        datos del modelo de navegación a los distintos widgets
        """

        self.printProgressBar = QProgressBar(self)
        self.webview = QWebView()
        """
        @ivar: EL objeto webview usado para cargar los reportes
        @type: QWebView
        """
        self.loaded = False
        """
        @ivar: Si se pudo o no cargar un reporte
        @type: bool
        """

        self.startUi()

        self.editmodel = None
        self.printer = QPrinter()

        self._status = False

    def startUi(self):
        """
        Iniciar todos los elementos graficos
        """
        self.setupUi(self)
        if not self.own_toolbar:
            self.parent().addToolBar(self.toolBar)
            self.removeToolBar(self.toolBar)

        settings = QSettings()
        self.restoreState(settings.value(self.windowTitle() + "/State").toByteArray())

        """
        @ivar: El MainWindow al que pertenece este widget
        """
        self.createActions()

        self.printProgressBar.setVisible(False)

        _tab1shortcut = QShortcut(QKeySequence("Ctrl+1"), self, functools.partial(self.tabWidget.setCurrentIndex, 0))
        _tab2shortcut = QShortcut(QKeySequence("Ctrl+2"), self, functools.partial(self.tabWidget.setCurrentIndex, 1))

        self.mapper.currentIndexChanged[int].connect(self.updateDetailFilter)

        self.actionCut.setVisible(False)
        self.actionPaste.setVisible(False)
        self.actionCopy.setVisible(False)

    def closeEvent(self, event):
        u"""
        Guardar el tamaño, la posición en la pantalla y la posición de
         la barra de tareas
        Preguntar si realmente se desea cerrar la pestaña cuando
         se esta en modo edición
        """
        if not self.status:
            if (
                not QMessageBox.question(
                    self, qApp.organizationName(), u"¿Está seguro que desea salir?", QMessageBox.Yes | QMessageBox.No
                )
                == QMessageBox.Yes
            ):
                event.ignore()

        # Guardar el tamaño y la posición
        settings = QSettings()
        settings.setValue(self.windowTitle() + "/Geometry", self.saveGeometry())

        if not self.own_toolbar:
            self.parent().mdiArea().parent().parent().removeToolBar(self.toolBar)

    def editCell(self):
        """
        Editar la celda actualmente seleccionada de self.tableedit
        """
        self.tabledetails.edit(self.tabledetails.selectionModel().currentIndex())

    @pyqtSlot(QDateTime)
    @if_edit_model
    def on_dtPicker_dateTimeChanged(self, datetime):
        """
        Cambiar el tipo de cambio del modelo de edición si cambia la fecha
        @param datetime: La fecha contenida en self.dtPicker
        @type datetime: QDateTime
        """
        query = QSqlQuery()
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise Exception(
                        "No se pudo conectar a la base de " + "datos para recuperar los tipos " + "de cambio"
                    )

            q = """
                SELECT idtc, tasa
                FROM tiposcambio
                WHERE fecha = %s
                LIMIT 1
            """ % datetime.toString(
                "yyyyMMdd"
            )

            if not query.exec_(q):

                raise UserWarning("No se pudieron recuperar los tipos de " + "cambio")
            if not query.size() == 1:
                logging.critical(u"La consulta para obtener tipos de " + "cambio no devolvio exactamente un valor")
                raise UserWarning(u"Hubo un error al obtener los tipos " + "de cambio")

            query.first()
            self.editmodel.exchangeRateId = query.value(0).toInt()[0]
            self.editmodel.exchangeRate = Decimal(query.value(1).toString())

            # self.editmodel.setData( self.editmodel.index( 0, 0 ), self.editmodel.index( 0, 0 ).data() )

            self.editmodel.datetime = datetime
        except UserWarning as inst:
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
            self.dtPicker.setDateTime(self.editmodel.datetime)
            logging.error(inst)
            logging.error(query.lastError().text())
        except Exception as inst:
            QMessageBox.critical(self, qApp.organizationName(), u"Hubo un error al obtener los tipos de" + " cambio")
            logging.critical(query.lastError().text())
            logging.critical(inst)
            self.dtPicker.setDateTime(self.editmodel.datetime)

    def navigate(self, to):
        """
        Esta funcion se encarga de navegar entro los distintos documentos
        @param to: es una string que puede tomar los valores 'next' 'previous'
         'first' 'last'
        """
        if self.mapper.currentIndex != -1:
            row = self.mapper.currentIndex()
            if to == "next":
                row += 1
                if row >= self.navproxymodel.rowCount():
                    row = self.navproxymodel.rowCount() - 1
                self.mapper.setCurrentIndex(row)
            elif to == "previous":
                if row <= 1:
                    row = 0
                else:
                    row = row - 1
                self.mapper.setCurrentIndex(row)
            elif to == "first":
                self.mapper.toFirst()
            elif to == "last":
                self.mapper.toLast()
        else:
            self.mapper.toLast()()

        if self.tabledetails != None:
            self.tabledetails.resizeColumnsToContents()
            self.tabledetails.horizontalHeader().setStretchLastSection(True)
        self.tablenavigation.selectRow(self.mapper.currentIndex())

    def updateDetailFilter(self, _index):
        """
        Esta función se debe implementar en los formularios para que al 
        navegar se actualize el filtro de la tabla detalles
        @param index: Este es el indice del mapper en el que actualmente 
        se encuentra navegando
        @type index: int 
        """
        QMessageBox.information(self, qApp.organizationName(), u"Esta parte del sistema no ha " + "sido implementada")
        raise NotImplementedError()

    def loadModels(self):
        """
        Esta función se ejecuta en el constructor del formulario mediante
        un QTimer, carga los formularios por primera vez
        """
        self.updateModels()

        self.navigate("last")
        self.status = True

    def _setStatus(self, stat):
        """
        @param stat:  False = editando, True = navegando
        @type stat: bool
        """
        self._status = stat
        self.setControls(self._status)

    def _getStatus(self):
        """
        esta propiedad cambia entre navegar y editar
        """
        return self._status

    status = property(_getStatus, _setStatus)

    @pyqtSlot(unicode)
    def on_txtSearch_textChanged(self, searchstring):
        """
        Cambiar el filtro para el navigation model
        @param searchstring: Es el contenido por el cual se va a 
        filtrar el modelo de navegación
        @type searchstring: string
        """
        self.navproxymodel.setFilterFixedString(searchstring)

    @pyqtSlot(QModelIndex)
    def on_tablenavigation_doubleClicked(self, index):
        """
        Al hacer doble click en la tabla de navegación el se cambia a la
        pestaña detalles mostrando el documento seleccionado
        @param index: El indice de la tabla en la que se dio doble click
        @type index: QModelIndex 
        """
        self.mapper.setCurrentIndex(index.row())
        self.tabWidget.setCurrentIndex(0)

    @pyqtSlot(QModelIndex)
    def on_tablenavigation_clicked(self, index):
        self.mapper.setCurrentIndex(index.row())

    def save(self, ask=True):
        """
        Guardar el documento actual
        @param ask: Si se deberia o no preguntar al usuario si 
            esta seguro antes de proceder
        @type ask: bool
        """
        if (
            ask == False
            or QMessageBox.question(
                self, qApp.organizationName(), u"¿Esta seguro que desea guardar?", QMessageBox.Yes | QMessageBox.No
            )
            == QMessageBox.Yes
        ):
            if self.editmodel.valid:
                if self.editmodel.save():
                    QMessageBox.information(self, qApp.organizationName(), u"El documento se ha guardado con éxito")
                    self.editmodel = None
                    self.updateModels()
                    self.navigate("last")
                    self.status = True
                else:
                    QMessageBox.critical(self, qApp.organizationName(), "Ha ocurrido un error al guardar el documento")

            else:
                try:
                    QMessageBox.warning(self, qApp.organizationName(), self.editmodel.validError)
                except AttributeError:
                    QMessageBox.warning(
                        self,
                        qApp.organizationName(),
                        u"El documento no puede guardarse" + " ya que la información no esta" + " completa",
                    )

    def setControls(self, unused_status):
        """
        Habilitar o deshabilitar los controles según status
        @param status: 
        @type status: bool
        """
        QMessageBox.information(self, qApp.organizationName(), u"Esta parte del sistema no ha sido implementada")
        raise NotImplementedError()

    def addLine(self):
        """
        añadir una linea a table edit, solo se llama directamente 
        en una ocasion, al comenzar la edicion de un documento
        """
        row = self.editmodel.rowCount()
        self.editmodel.insertRows(row)

    def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered"):
        """
        Crear un objeto acción
        @param text: El texto de la acción
        @type text: string

        @param slot: El slot que se ejecutara cuando se dispare esta acción
        @type slot: callable

        @param shortcut: El acceso directo que tiene asignada esta acción
        @type shortcut: QKeySequence

        @param icon: El icono de esta acción
        @type icon: string

        @param tip: El tooltip que tendra esta acción
        @type tip: string

        @param checkable: Si esta acción es checkable o no
        @type checkable: bool

        @param signal: La señal en la que esta acción ejecutara el slot
        @type signal: string

        @rtype: QAction
        """
        action = QAction(text, self)
        if icon is not None:
            if type(icon) == QIcon:
                action.setIcon(icon)
            else:
                action.setIcon(QIcon(icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            getattr(action, signal).connect(slot)
        if checkable:
            action.setCheckable(True)
        return action

    def newDocument(self):
        """
        Empezar la edición de un nuevo documento
        """
        QMessageBox.information(self, qApp.organizationName(), u"Esta parte del sistema no ha sido implementada")
        raise NotImplementedError()

    def cancel(self):
        """
        Cancelar la edición del nuevo documento
        """
        QMessageBox.information(self, qApp.organizationName(), u"Esta parte del sistema no ha sido implementada")
        raise NotImplementedError()

    @property
    def printIdentifier(self):
        """
        La identificación de este documento para reporte,
         normalmente sera el iddocumento o el ndocimpreso
        @rtype:string
        """
        raise NotImplementedError(u"printIdentifier debe implementarse para " + "poder imprimir")

    def preview(self):
        """
        Muestra el dialogo de vista previa de impresión
        """
        try:
            printer = QPrinter()
            printer.setOrientation(self.orientation)
            printer.setPageSize(self.pageSize)
            web = self.web + self.printIdentifier
            report = reports.frmReportes(web, printer, self)
            report.exec_()
        except NotImplementedError as inst:
            QMessageBox.information(
                self, qApp.organizationName(), u"No se ha implementado la función de impresión para este modulo"
            )
            logging.error(unicode(inst))
        except UserWarning as inst:
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
            logging.error(unicode(inst))
        except Exception as inst:
            QMessageBox.critical(self, qApp.organizationName(), "Hubo un error al intentar mostrar su reporte")
            logging.critical(unicode(inst))

    def printDocument(self):
        """
        Imprime el documento actual
        """
        try:

            base = reports.Reports.url

            if base == "":
                raise UserWarning(u"No existe una configuración para el " + "servidor de reportes")

            self.printer.setOrientation(self.orientation)
            self.printer.setPageSize(self.pageSize)

            web = base + self.web + self.printIdentifier + "&uname=" + self.user.user + "&hash=" + self.user.hash
            self.loaded = False

            self.webview.load(QUrl(web))

            self.webview.loadFinished[bool].connect(self.on_webview_loadFinished)
            self.webview.loadProgress[int].connect(self.on_webview_loadProgress)
        except NotImplementedError as inst:
            logging.error(unicode(inst))
            QMessageBox.information(
                self, qApp.organizationName(), u"La función de impresión no se ha " + "implementado para este modulo"
            )
        except UserWarning as inst:
            logging.error(unicode(inst))
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
        except Exception as inst:
            logging.critical(unicode(inst))
            QMessageBox.critical(self, qApp.organizationName(), "Hubo un problema al intentar imprimir" + " su reporte")

    def on_webview_loadProgress(self, progress):
        """
        Muestra el progreso de la carga del reporte en un progressBar
        """
        self.printProgressBar.setValue(progress)

    def on_webview_loadFinished(self, status):
        if self.printProgressBar.isVisible():
            self.printProgressBar.hide()
        if not status:
            QMessageBox.critical(self, qApp.organizationName(), "El reporte no se pudo cargar")
            logging.error("No se pudo cargar el reporte")

        self.loaded = True

        printdialog = QPrintDialog(self.printer, self)
        if printdialog.exec_() == QDialog.Accepted:
            self.webview.print_(self.printer)

        del self.webview

    def deleteRow(self):
        """
        Funcion usada para borrar lineas de la tabla
        """
        index = self.tabledetails.currentIndex()

        if not index.isValid():
            return
        row = index.row()

        self.editmodel.removeRows(row, 1)
        self.updateLabels()

    def updateLabels(self):
        """
        Este metodo se llama para actualizar las etiquetas de totales en el
        formulario
        """
        raise NotImplementedError()

    def createActions(self):
        """
        Crea las acciones predefinidas del sistema
        """
        self.actionNew = self.createAction(
            text="Nuevo",
            tip="Crear un nuevo documento",
            icon=QIcon.fromTheme("document-new", QIcon(":/icons/res/document-new.png")),
            shortcut="Ctrl+n",
            slot=self.newDocument,
        )
        self.actionPreview = self.createAction(
            text="Previsualizar",
            tip=u"Vista de impresión del documento",
            icon=QIcon.fromTheme("document-preview", QIcon(":/icons/res/document-preview.png")),
            shortcut="Ctrl+p",
            slot=self.preview,
        )
        self.actionPrint = self.createAction(
            text="Imprimir",
            tip="Imprimir el documento",
            icon=QIcon.fromTheme("document-print", QIcon(":/icons/res/document-print.png")),
            slot=self.printDocument,
        )
        self.actionSave = self.createAction(
            text="Guardar",
            tip="Guardar el documento",
            icon=QIcon.fromTheme("document-save", QIcon(":/icons/res/document-save.png")),
            shortcut="Ctrl+g",
            slot=self.save,
        )
        self.actionCancel = self.createAction(
            text="Cancelar",
            tip=u"Cancelar la creación del nuevo documento",
            icon=QIcon.fromTheme("dialog-cancel", QIcon(":/icons/res/dialog-cancel.png")),
            shortcut="Esc",
            slot=self.cancel,
        )

        # edicion, TODO: QUE FUNCIONEN ESTAS ACCIONES
        self.actionCopy = self.createAction(
            text="Copiar", icon=QIcon.fromTheme("edit-copy", QIcon(":/icons/res/edit-copy.png")), shortcut="Ctrl+c"
        )
        self.actionCut = self.createAction(
            text="Cortar", icon=QIcon.fromTheme("edit-cut", QIcon(":/icons/res/edit-cut.png")), shortcut="Ctrl+x"
        )
        self.actionPaste = self.createAction(text="Pegar", icon=":/icons/res/edit-paste.png", shortcut="Ctrl+v")

        # navegación
        self.actionGoFirst = self.createAction(
            text="Primer documento",
            tip="Ir al primer documento",
            icon=QIcon.fromTheme("go-first", QIcon(":/icons/res/go-first.png")),
            slot=functools.partial(self.navigate, "first"),
        )
        self.actionGoPrevious = self.createAction(
            text="Documento anterior",
            tip="Ir al documento anterior",
            icon=QIcon.fromTheme("go-previous", QIcon(":/icons/res/go-previous.png")),
            slot=functools.partial(self.navigate, "previous"),
        )
        self.actionGoLast = self.createAction(
            text="Ultimo documento",
            tip="Ir al ultimo documento",
            icon=QIcon.fromTheme("go-last", QIcon(":/icons/res/go-last.png")),
            slot=functools.partial(self.navigate, "last"),
        )
        self.actionGoNext = self.createAction(
            text="Documento siguiente",
            tip="Ir al siguiente documento",
            icon=QIcon.fromTheme("go-next", QIcon(":/icons/res/go-next.png")),
            slot=functools.partial(self.navigate, "next"),
        )

        self.actionDeleteRow = self.createAction(
            text="Borrar la fila",
            icon=QIcon.fromTheme("edit-delete", QIcon(":/icons/res/edit-delete.png")),
            slot=self.deleteRow,
        )

        self.addActionsToToolBar()

    def addActionsToToolBar(self):
        """
        Añade las acciones predefinidas a la barra de tareas
        """
        self.toolBar.addActions(
            [self.actionNew, self.actionPreview, self.actionPrint, self.actionSave, self.actionCancel]
        )
        self.toolBar.addSeparator()

        self.toolBar.addActions(
            [self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast]
        )

    @pyqtSlot()
    @if_edit_model
    def on_txtObservations_textChanged(self):
        """
        Asignar las observaciones al editmodel
        """
        self.editmodel.observations = self.txtObservations.toPlainText().strip()
Exemple #18
0
class Entity(QWidget):
    def __init__(self, base_image, size, hp=100, pos=(0, 0), parent=None):
        super().__init__(parent)
        self._base_label = QLabel(self)
        self._base_image = base_image
        self._size = size
        self._decor_label = None
        self._decor_pixmap = None
        self._hp_max = hp

        self.__pixmap = None
        """:type: PyQt4.QtGui.QPixmap"""

        self.__cord_x = pos[0]
        self.__cord_y = pos[1]
        self.__angle = 0

        self.__hp_bar = QProgressBar(self)
        self.__hp_bar.setMaximum(self._hp_max)
        self.__hp_bar.setValue(self._hp_max)
        self.__hp_bar.setTextVisible(False)
        self.__hp_bar.setMaximumSize(size[0], 5)

        self.setAlignment(Qt.AlignCenter)
        self.updatePixmap()

        if _debugging:
            self.setStyleSheet("border: 1px solid black")

    @property
    def health(self):
        return self.__hp_bar.value()

    @health.setter
    def health(self, hp):
        if hp > self._hp_max:
            hp = self._hp_max
        elif hp < 0:
            hp = 0
        self.__hp_bar.setValue(hp)

    @property
    def angle(self):
        return self.__angle

    @angle.setter
    def angle(self, angle):
        self.__angle = angle
        self.updatePixmap()

    @property
    def cord_x(self):
        return self.__cord_x

    @cord_x.setter
    def cord_x(self, cord):
        self.__cord_x = cord
        self.move(self.cord_x, self.cord_y)

    @property
    def cord_y(self):
        return self.__cord_y

    @cord_y.setter
    def cord_y(self, cord):
        self.__cord_y = cord
        self.move(self.cord_x, self.cord_y)

    def hide_hp_bar(self, bool=False):
        if bool:
            self.__hp_bar.hide()
        else:
            self.__hp_bar.show()

    def add_decoration(self, path):
        if path is None:
            self._decor_label.deleteLater()
            self._decor_label = None
        else:
            self._decor_label = QLabel(self)
            self._decor_pixmap = QPixmap(path)
            # self._decor_pixmap = self._decor_pixmap.scaled(self._size[0], self._size[1])
            self._decor_pixmap = self._decor_pixmap.transformed(
                QTransform().rotate(self.angle))
            self._decor_label.setPixmap(self._decor_pixmap)
            self._decor_label.setAlignment(Qt.AlignCenter)
            self._decor_label.show()

    def updatePixmap(self):
        path = get_asset_path(self._base_image)
        self.__pixmap = QPixmap(path)
        self.__pixmap = self.__pixmap.scaled(self._size[0], self._size[1])
        self.__pixmap = self.__pixmap.transformed(QTransform().rotate(
            self.angle))
        self._base_label.setPixmap(self.__pixmap)
        self._base_label.show()
        # self.setFixedSize(self.__pixmap.width(), self.__pixmap.height())

    def setFixedSize(self, x, y):
        super().setFixedSize(x, y)
        self._base_label.setFixedSize(x, y)

    def setAlignment(self, alignment):
        self._base_label.setAlignment(alignment)
Exemple #19
0
class GUI(QWidget):

    def __init__(self, parent=None):
        super(GUI, self).__init__(parent)

        self.create_ui_components()
        self.compose_ui()

        # Initializing: window composition, it's contents and event handlers
        self.init_composition()
        self.init_contents()
        self.init_actions()

        self.on_start()

    def create_ui_components(self):
        """
        Create layouts and qt controls.
        """
        self.layout = QGridLayout()

        self.kanjiGroup = QGroupBox()
        self.kanjiLayout = QGridLayout()

        # Kanji ui group
        self.day, self.week, self.month, self.year = \
        QLabel(KANJI), QLabel(KANJI), QLabel(KANJI), QLabel(KANJI)

        self.dayLabel, self.weekLabel, self.monthLabel, self.yearLabel = \
        QLabel('<b>Day</b>'), QLabel('<b>Week</b>'), \
        QLabel('<b>Month</b>'), QLabel('<b>Year</b>')

        # Main layout
        self.showAbout = QPushButton('A&bout')
        # DB controls (top)
        self.showDB, self.availableDB, self.changeDB = \
        QPushButton('&Change DB (active:)'), QComboBox(), QPushButton('&Remap')
        # General controls (bottom)
        self.getAll, self.showStats, self.quitApp, self.authGen, self.methodCombo = \
        QPushButton('&Get all'), QPushButton('&Stats'), QPushButton('&Quit'), \
        QPushButton('&Auth'), QComboBox()
        # Notifications
        self.progressBar = QProgressBar()
        self.statusMessage = QLabel()
        # About
        self.aboutBox = QMessageBox()

    def compose_ui(self):
        """
        Fill layouts and groups, initialize filters.
        """
        self.kanjiLayout.addWidget(self.day, 0, 0)
        self.kanjiLayout.addWidget(self.week, 0, 1)
        self.kanjiLayout.addWidget(self.dayLabel, 1, 0)
        self.kanjiLayout.addWidget(self.weekLabel, 1, 1)

        self.kanjiLayout.addWidget(self.month, 2, 0)
        self.kanjiLayout.addWidget(self.year, 2, 1)
        self.kanjiLayout.addWidget(self.monthLabel, 3, 0)
        self.kanjiLayout.addWidget(self.yearLabel, 3, 1)

        self.kanjiGroup.setLayout(self.kanjiLayout)

        self.layout.addWidget(self.showDB, 0, 0, 1, 2)
        self.layout.addWidget(self.availableDB, 1, 0)
        self.layout.addWidget(self.changeDB, 1, 1)
        self.layout.addWidget(self.kanjiGroup, 2, 0, 1, 2)
        self.layout.addWidget(self.getAll, 3, 0)
        self.layout.addWidget(self.showStats, 3, 1)
        self.layout.addWidget(self.methodCombo, 4, 0)
        self.layout.addWidget(self.authGen, 4, 1)
        #self.layout.addWidget(self.quitApp, 5, 0, 1, 2)
        self.layout.addWidget(self.quitApp, 5, 0)
        self.layout.addWidget(self.showAbout, 5, 1)
        self.layout.addWidget(self.progressBar, 6, 0, 1, 2)
        self.layout.addWidget(self.statusMessage, 7, 0, 1, 2)

        self.setLayout(self.layout)

        self.eFilter = LabelEventFilter()

    def on_start(self):
        """
        Additional procedures run on application start.
        """
        # Let's initialize even some stuff!
        self.al = None
        self.auth_thread = None
        self.init_backend()

        choose_db(str(self.availableDB.currentText()))
        self.showDB.setText("&Change DB (active: %s)" % self.availableDB.currentText())

        self.stats = StatsUI(self.al, self)

    def init_composition(self):
        """
        Window composition and general params.
        """
        self.setWindowTitle(NAME + ' ' + __version__)
        desktop = QApplication.desktop()
        self.setGeometry((desktop.width() - WIDTH)/2,
                        (desktop.height() - HEIGHT)/2, WIDTH, HEIGHT)

    def init_contents(self):
        """
        Setting up qt controls.
        """
        self.changeDB.hide()
        self.availableDB.hide()
        self.availableDB.addItems(dbs.keys())

        self.kanjiGroup.setAlignment(Qt.AlignCenter)
        self.kanjiGroup.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px; }")

        self.day.setAlignment(Qt.AlignCenter)
        self.week.setAlignment(Qt.AlignCenter)
        self.month.setAlignment(Qt.AlignCenter)
        self.year.setAlignment(Qt.AlignCenter)
        self.dayLabel.setAlignment(Qt.AlignCenter)
        self.weekLabel.setAlignment(Qt.AlignCenter)
        self.monthLabel.setAlignment(Qt.AlignCenter)
        self.yearLabel.setAlignment(Qt.AlignCenter)

        self.day.setFont(QFont(PRETTY_FONT, KANJI_SIZE))
        self.week.setFont(QFont(PRETTY_FONT, KANJI_SIZE))
        self.month.setFont(QFont(PRETTY_FONT, KANJI_SIZE))
        self.year.setFont(QFont(PRETTY_FONT, KANJI_SIZE))

        self.methodCombo.addItems(RandomMess.algs.keys())
        self.methodCombo.setCurrentIndex(1)

        self.statusMessage.setAlignment(Qt.AlignCenter)
        self.statusMessage.hide()
        self.statusMessage.setMaximumHeight(MESSAGE_HEIGHT)
        self.statusMessage.setStyleSheet(WARNING_STYLE)

        self.progressBar.setMaximum(0)
        self.progressBar.setMaximumHeight(PROGRESS_HEIGHT)
        self.progressBar.hide()

        QToolTip.setFont(QFont(PRETTY_FONT, TOOLTIP_FONT_SIZE))

        self.getAll.setToolTip('Randomly select all 4 kanji')
        self.methodCombo.setToolTip('Choose algorithm for randomness')
        self.authGen.setToolTip('Authorize on remote RNG services')
        self.showStats.setToolTip('Show/hide dialog with comprehensive statistics')
        self.quitApp.setToolTip('Close application')
        self.showDB.setToolTip('Show/hide available databases')
        self.availableDB.setToolTip('Available kanji frequency charts db')
        self.changeDB.setToolTip('Pick new kanji from currently selected db')

        # About dialog
        self.aboutBox.layout().itemAt(1).widget().setAlignment(Qt.AlignLeft)

        self.aboutBox.setTextFormat(Qt.RichText)
        self.aboutBox.setText('Version:\t<b>' + __version__ + '</b><br/>Python:\t<b>' + platform.python_version() + '</b>' +
                                '<br/>Platform:\t<b>' + platform.system() + ' ' + platform.release() + '</b>' +
                                '<br/>Author:\t<b>' + __author__ + '</b>' + app_about)
        self.aboutBox.setWindowTitle('About ' + app_name)
        self.aboutBox.setIconPixmap(QPixmap(paths['icon']))

    def init_actions(self):
        """
        Binding events/handlers.
        """
        self.showDB.clicked.connect(self.show_available_db)
        self.changeDB.clicked.connect(self.change_db)

        self.quitApp.clicked.connect(self.close)
        self.getAll.clicked.connect(self.get_all)
        self.authGen.clicked.connect(self.auth_task)
        self.showStats.clicked.connect(self.show_stats)
        self.methodCombo.currentIndexChanged.connect(self.update_alg)

        self.showAbout.clicked.connect(self.app_help)

        # Mouse events for labels
        self.day.setAttribute(Qt.WA_Hover, True)
        self.week.setAttribute(Qt.WA_Hover, True)
        self.month.setAttribute(Qt.WA_Hover, True)
        self.year.setAttribute(Qt.WA_Hover, True)
        self.day.installEventFilter(self.eFilter)
        self.week.installEventFilter(self.eFilter)
        self.month.installEventFilter(self.eFilter)
        self.year.installEventFilter(self.eFilter)

    ##### actions #####

    def show_stats(self):
        if self.stats.isVisible():
            self.stats.hide()
        else:
            self.stats.show()

    def show_available_db(self):
        if self.availableDB.isVisible():
            self.availableDB.hide()
            self.changeDB.hide()
        else:
            self.availableDB.show()
            self.changeDB.show()

    def change_db(self):
        try:
            choose_db(str(self.availableDB.currentText()))
            self.availableDB.hide()
            self.changeDB.hide()
            self.show_message_then_hide("DB successfully remaped!", False)
            self.showDB.setText("&Change DB (active: %s)" % self.availableDB.currentText())

            self.stats.update_stat_info()
            self.stats.refresh_plot()
        except NoDbException as e:
            self.show_message_then_hide(e.message)

    def get_all(self):
        self.random_kanji_task = RandomKanjiTask(self.al)
        self.random_kanji_task.done.connect(self.update_kanji)
        self.show_progress('Selecting kanji...')
        self.random_kanji_task.start()

    def update_kanji(self, results):
        if results['success']:
            kanji_set = results['kanji_set']
            for_a_day = kanji_set.pop()
            for_a_week = kanji_set.pop()
            for_a_month = kanji_set.pop()
            for_a_year = kanji_set.pop()

            self.day.setText(for_a_day.character)
            self.dayLabel.setText('<b>Day:</b> ' + str(for_a_day.frequency) + ' | '
                                        + str(for_a_day.dominance) + '%')
            self.week.setText(for_a_week.character)
            self.weekLabel.setText('<b>Week:</b> ' + str(for_a_week.frequency) + ' | '
                                        + str(for_a_week.dominance) + '%')
            self.month.setText(for_a_month.character)
            self.monthLabel.setText('<b>Month:</b> ' + str(for_a_month.frequency) + ' | '
                                        + str(for_a_month.dominance) + '%')
            self.year.setText(for_a_year.character)
            self.yearLabel.setText('<b>Year:</b> ' + str(for_a_year.frequency) + ' | '
                                        + str(for_a_year.dominance) + '%')

            self.kanji_tooltip(self.day)
            self.kanji_tooltip(self.week)
            self.kanji_tooltip(self.month)
            self.kanji_tooltip(self.year)

            if self.stats.isVisible():
                self.stats.update_stat_info()
                self.stats.refresh_plot()

            self.hide_message()
        else:
            self.show_message_then_hide(results['message'])

        self.hide_progress()

    def pretty_font(self):
        pass

    def update_alg(self):
        self.al.set_active(str(self.methodCombo.currentText()))

    def init_backend(self):
        self.al = RandomMess()
        self.update_alg()

    def auth_task(self):
        self.auth_thread = AuthorizationTask(self.al)
        self.auth_thread.done.connect(self.auth_complete)
        #self.auth_thread.run()
        # IT DOESN't work on windows as it should!
        self.auth_thread.start()
        self.show_progress('Authorizing on RNG services...')

    def auth_complete(self, success):
        self.hide_message()
        self.hide_progress()
        if success:
            self.show_message_then_hide("Successfully authenticated!", False)
        else:
            self.show_message_then_hide("Sorry, could not authenticate.")

    def show_message_then_hide(self, message, error=True):
        if error:
            self.statusMessage.setStyleSheet(WARNING_STYLE)
        else:
            self.statusMessage.setStyleSheet(NOTE_STYLE)

        self.statusMessage.setText(message)
        self.statusMessage.show()
        QTimer.singleShot(MESSAGE_TIMEOUT, self.hide_message)

    def show_progress(self, message):
        self.statusMessage.setStyleSheet(NOTE_STYLE)
        self.statusMessage.setText(message)
        self.statusMessage.show()
        self.progressBar.show()

    def hide_message(self):
        self.statusMessage.setText('')
        self.statusMessage.hide()

    def hide_progress(self):
        self.progressBar.hide()

    def toggle_kanji_info(self, label, info):
        label.setToolTip(info.info())

    def kanji_tooltip(self, label):
        found = JDIC.search(label.text())
        if found:
            label.setToolTip(found.info())
        else:
            label.setToolTip('No such kanji in kanjidic2!')

    def kanji_info(self, kanji):
        pass

    def app_help(self):
        self.aboutBox.show()

        #### Utility events ####

    def resizeEvent(self, QResizeEvent):
        self.updateStatsPosition()
        self.updateStatsSize()

    def moveEvent(self, QMoveEvent):
        self.updateStatsPosition()
        self.updateStatsSize()

    def updateStatsPosition(self):
        self.stats.move(self.x() + self.width() + 20, self.y())

    def updateStatsSize(self):
        self.stats.resize(QSize(self.stats.width(), self.height()))
Exemple #20
0
class LabelAssistDialog(QDialog):
    """
    A simple UI for showing bookmarks and navigating to them.

    FIXME: For now, this window is tied to a particular lane.
           If your project has more than one lane, then each one
           will have it's own bookmark window, which is kinda dumb.
    """
    def __init__(self, parent, topLevelOperatorView):
        super(LabelAssistDialog, self).__init__(parent)
        
        # Create thread router to populate table on main thread
        self.threadRouter = ThreadRouter(self)
        
        # Set object classification operator view
        self.topLevelOperatorView = topLevelOperatorView
        
        self.setWindowTitle("Label Assist")
        self.setMinimumWidth(500)
        self.setMinimumHeight(700)

        layout = QGridLayout() 
        layout.setContentsMargins(10, 10, 10, 10)
                       
        # Show variable importance table
        rows = 0
        columns = 4
        self.table = QTableWidget(rows, columns)   
        self.table.setHorizontalHeaderLabels(['Frame', 'Max Area', 'Min Area', 'Labels'])
        self.table.verticalHeader().setVisible(False)     
        
        # Select full row on-click and call capture double click
        self.table.setSelectionBehavior(QTableView.SelectRows);
        self.table.doubleClicked.connect(self._captureDoubleClick)
                
        layout.addWidget(self.table, 1, 0, 3, 2) 

        # Create progress bar
        self.progressBar = QProgressBar()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.hide()
        layout.addWidget(self.progressBar, 4, 0, 1, 2)

        # Create button to populate table
        self.computeButton = QPushButton('Compute object info')
        self.computeButton.clicked.connect(self._triggerTableUpdate)
        layout.addWidget(self.computeButton, 5, 0)
        
        # Create close button
        closeButton = QPushButton('Close')
        closeButton.clicked.connect(self.close)
        layout.addWidget(closeButton, 5, 1)
        
        # Set dialog layout
        self.setLayout(layout)       


    def _triggerTableUpdate(self):
        # Check that object area is included in selected features
        featureNames = self.topLevelOperatorView.SelectedFeatures.value
        
        if 'Standard Object Features' not in featureNames or 'Count' not in featureNames['Standard Object Features']:
            box = QMessageBox(QMessageBox.Warning,
                  'Warning',
                  'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"',
                  QMessageBox.NoButton,
                  self)
            box.show()
            return 
        
        # Clear table
        self.table.clearContents()
        self.table.setRowCount(0)
        self.table.setSortingEnabled(False)
        self.progressBar.show()
        self.computeButton.setEnabled(False)

        def compute_features_for_frame(tIndex, t, features): 
            # Compute features and labels (called in parallel from request pool)
            roi = [slice(None) for i in range(len(self.topLevelOperatorView.LabelImages.meta.shape))]
            roi[tIndex] = slice(t, t+1)
            roi = tuple(roi)

            frame = self.topLevelOperatorView.SegmentationImages(roi).wait()           
            frame = frame.squeeze().astype(numpy.uint32, copy=False)
            
            # Dirty trick: We don't care what we're passing here for the 'image' parameter,
            # but vigra insists that we pass *something*, so we'll cast the label image as float32.
            features[t] = vigra.analysis.extractRegionFeatures(frame.view(numpy.float32),
                                                               frame,
                                                               ['Count'],
                                                               ignoreLabel=0)
            
        tIndex = self.topLevelOperatorView.SegmentationImages.meta.axistags.index('t')
        tMax = self.topLevelOperatorView.SegmentationImages.meta.shape[tIndex]     
        
        features = {}
        labels = {}

        def compute_all_features():
            # Compute features in parallel
            pool = RequestPool()
            for t in range(tMax):
                pool.add( Request( partial(compute_features_for_frame, tIndex, t, features) ) )
            pool.wait()
            
        # Compute labels
        labels = self.topLevelOperatorView.LabelInputs([]).wait()
            
        req = Request(compute_all_features)
        req.notify_finished( partial(self._populateTable, features, labels) )
        req.submit()

    @threadRouted
    def _populateTable(self, features, labels, *args):
        self.progressBar.hide()
        self.computeButton.setEnabled(True)
                
        for time, feature in features.iteritems():
            # Insert row
            rowNum = self.table.rowCount()
            self.table.insertRow(self.table.rowCount())
            
            # Get max and min object areas
            areas = feature['Count']#objectFeatures['Standard Object Features']['Count']
            maxObjArea = numpy.max(areas[numpy.nonzero(areas)])
            minObjArea = numpy.min(areas[numpy.nonzero(areas)])
            
            # Get number of labeled objects
            labelNum = numpy.count_nonzero(labels[time])
            
            # Load fram number
            item = QTableWidgetItem(str(time))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 0, item) 

            # Load max object areas
            item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(maxObjArea)))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 1, item)
                
            # Load min object areas
            item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(minObjArea)))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 2, item)
            
            # Load label numbers
            item = QTableWidgetItemWithFloatSorting(str("{: .01f}".format(labelNum)))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 3, item)
        
        # Resize column size to fit dialog size
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)   
        
        # Sort by max object area
        self.table.setSortingEnabled(True)                         
        self.table.sortByColumn(1) 
        

    def _captureDoubleClick(self):
        # Navigate to selected frame
        index = self.table.selectedIndexes()[0]
        frameStr = self.table.model().data(index).toString()
        
        if frameStr:
            frameNum = int(frameStr)
            self.parent().editor.posModel.time = frameNum
Exemple #21
0
Fichier : scj.py Projet : Ptaah/SCJ
class SCJProgress(QHBoxLayout):
    def __init__(self, parent=None, file=None, format=None, createDir=False ):
        super(SCJProgress, self).__init__(parent)
        self.format = format
        self.filename = file
        self.createDir = createDir
        self.process = SCJ(self.filename, self.format, createDir)
        self.output = QString(self.process.output)
        self.command = QStringList(self.process.command)
        self.log = QStringList()

        self.label = QLabel(self.output)
        self.label.setToolTip(self.trUtf8("Destination: %s" % self.output))
        self.bar = QProgressBar(parent)
        self.bar.setToolTip(self.trUtf8("Source: %s" % self.filename))
        self.bar.setValue(0)
        self.startbtn = QPushButton(parent) 
        self.stopbtn = QPushButton(parent)
        self.cancelbtn = QPushButton(parent)
        self.logbtn = QPushButton(parent)
        self.cancelbtn.setMinimumSize(32,32)
        self.cancelbtn.setFlat(True)
        self.startbtn.setMinimumSize(32,32)
        self.startbtn.setFlat(True)
        self.stopbtn.setMinimumSize(32,32)
        self.stopbtn.setFlat(True)
        self.label.setMinimumSize(200,32)
        self.bar.setMinimumSize(100,16)
        self.bar.setMaximumHeight(16)

        self.addWidget(self.logbtn)
        self.logbtn.hide()
        self.addWidget(self.label)
        self.addWidget(self.bar)
        self.addWidget(self.startbtn)
        self.addWidget(self.stopbtn)
        self.addWidget(self.cancelbtn)
        self.retranslateUi()

        self.connect(self.startbtn, SIGNAL("clicked()"), self.start)
        self.connect(self.stopbtn, SIGNAL("clicked()"),  self.stop)
        self.connect(self.cancelbtn, SIGNAL("clicked()"), self.remove)
        self.connect(self.logbtn, SIGNAL('clicked()'), self.showLog)
        self.connect(self.process, SIGNAL('progress(int)'), self.bar.setValue)
        self.connect(self.process, SIGNAL('error(QString)'), self.addLog)
        self.connect(self.process, SIGNAL('finished()'), self.enable)

    def retranslateUi(self):
        self.startbtn.setIcon(QIcon(u"images/play.png"))
        self.startbtn.setToolTip(self.trUtf8("Demarrer"))
        self.stopbtn.setIcon(QIcon(u"images/stop.png"))
        self.stopbtn.setToolTip(self.trUtf8("Stopper"))
        self.cancelbtn.setIcon(QIcon(u"images/remove.png"))
        self.cancelbtn.setToolTip(self.trUtf8("Annuler"))
        self.logbtn.setIcon(QIcon(u"images/log.png"))
        self.logbtn.setToolTip(self.trUtf8("Voir les details"))

    def start(self):
        self.log.clear()
        self.logbtn.hide()
        self.disable()
        self.process.start()
        self.process.resume()

    def stop(self):
        self.process.cancel()
        self.process.terminate()
        self.enable()

    def remove(self):
        self.removeWidget(self.label)
        self.removeWidget(self.bar)
        self.removeWidget(self.startbtn)
        self.removeWidget(self.stopbtn)
        self.removeWidget(self.cancelbtn)
        self.removeWidget(self.logbtn)
        self.label.hide()
        self.bar.hide()
        self.startbtn.hide()
        self.stopbtn.hide()
        self.cancelbtn.hide()
        self.logbtn.hide()
        self.emit(SIGNAL("void removed(QString)"), self.output)

    def showLog(self):
        QMessageBox.critical(None, u"Ooops", self.log.join("\n"))

    def addLog(self, log):
        self.log.append(log)
        self.logbtn.show()
        palette = QPalette()
        brush = QBrush(QColor(240, 100, 100))
        brush.setStyle(Qt.SolidPattern)
        palette.setBrush(QPalette.Normal, QPalette.Background, brush)
        self.label.setPalette(palette)
        self.label.setAutoFillBackground(True)

    def enable(self):
        self.process = SCJ(self.filename, self.format, self.createDir)
        self.output = QString(self.process.output)
        self.command = QStringList(self.process.output)
        self.connect(self.process, SIGNAL('progress(int)'), self.bar.setValue)
        self.connect(self.process, SIGNAL('error(QString)'), self.addLog)
        self.connect(self.process, SIGNAL('finished()'), self.enable)
        self.cancelbtn.setEnabled(True)
        self.startbtn.setEnabled(True)

    def disable(self):
        self.cancelbtn.setEnabled(False)
        self.startbtn.setEnabled(False)
        self.label.setAutoFillBackground(False)
Exemple #22
0
class MainWindow(QMainWindow):
        def __init__(self):
                QMainWindow.__init__(self)
                
                self.ui = Ui_MainWindow()
                self.ui.setupUi(self)

                self.setCentralWidget(self.ui.mangaTableView)
                self.newMangaDialog = NewMangaDialog()
                self.mangaDownloadDialog = MangaDownloadDialog()

                self.mangaTableModel = QStandardItemModel(0, 3, self)
                self.mangaTableModel.setHorizontalHeaderItem(0, QStandardItem(QString("Manga")))
                self.mangaTableModel.setHorizontalHeaderItem(1, QStandardItem(QString("Latest Chapter")))
                self.mangaTableModel.setHorizontalHeaderItem(2, QStandardItem(QString("Status")))
                self.ui.mangaTableView.setModel(self.mangaTableModel)

                newMangaAction = QAction(QIcon("./icon/add.ico"),'New Manga', self)
                newMangaAction.setShortcut('Ctrl+N')
                newMangaAction.triggered.connect(self.newMangaDialog.show)

                removeMangaAction = QAction(QIcon("./icon/delete.ico"),'Remove Manga', self)
                removeMangaAction.setShortcut('Delete')

                preferencesAction = QAction(QIcon("./icon/preferences.ico"),'Preferences', self)                

                aboutAction = QAction(QIcon("./icon/about.ico"),'About', self)

                self.ui.toolBar.addAction(newMangaAction)
                self.ui.toolBar.addAction(removeMangaAction)
                self.ui.toolBar.addSeparator()
                self.ui.toolBar.addAction(preferencesAction)
                self.ui.toolBar.addSeparator()
                self.ui.toolBar.addAction(aboutAction)

                self.progressBar = QProgressBar(self.ui.statusbar)
                self.ui.statusbar.addPermanentWidget(self.progressBar)
                self.progressBar.hide()

        def closeEvent(self, QCloseEvent):
                mangaList = []
                for i in range(self.mangaTableModel.rowCount()):
                        mangaList.append({
                                                "name" : str(self.mangaTableModel.item(i, 0).text()),
                                                "latestChapter" : str(self.mangaTableModel.item(i, 1).text()),
                                                "status" : "Updated",
                                                "link" : "/trial.html"
                                        })
                self.emit(SIGNAL("applicationClosed"),mangaList)

        def initializeProgressBar(self, size):
                self.progressBar.setRange(0, size)
                self.progressBar.setValue(0)
                self.progressBar.show()

        def updateProgressBar(self, value):
                self.progressBar.setValue(value)

        def updateStatusBar(self, msg):
                self.ui.statusbar.showMessage(msg)

        def updateMangaTable(self, chapter):
                isFound = False
                for i in range(self.mangaTableModel.rowCount()):
                        mangaItem = self.mangaTableModel.item(i)
                        if mangaItem.text() == chapter["name"]:
                                self.mangaTableModel.item(i, 1).setText(chapter["latestChapter"])
                                self.mangaTableModel.item(i, 2).setText(chapter["status"])
                                isFound = True
                                break

                if not isFound:
                        self.addRowToMangaTable(chapter)

        def addMangaListToMangaTable(self, mangaList):
                for i in range(len(mangaList)):
                        self.addRowToMangaTable(mangaList[i])

        def addRowToMangaTable(self, manga):
                i = self.mangaTableModel.rowCount()

                mangaItem = QStandardItem(QString(manga["name"]))
                latestChapterItem = QStandardItem(QString(manga["latestChapter"]))
                statusItem = QStandardItem(QString(manga["status"]))

                brush = QBrush(QColor(255, 255, 255)) if i%2==0 else QBrush(QColor(200, 200, 200))

                mangaItem.setBackground(brush)
                latestChapterItem.setBackground(brush)
                statusItem.setBackground(brush)

                self.mangaTableModel.setItem(i, 0, mangaItem)
                self.mangaTableModel.setItem(i, 1, latestChapterItem)
                self.mangaTableModel.setItem(i, 2, statusItem)
Exemple #23
0
class InputForm(QWidget):

    __instance = None

    @staticmethod
    def instance():
        return InputForm.__instance

    def __init__(self):
        if not InputForm.__instance:
            InputForm.__instance = self

        super(InputForm, self).__init__()

        Global.event.task_started.connect(self._on_task_started)
        Global.event.task_completed.connect(self._on_task_completed)
        Global.event.task_progressed.connect(self._on_task_progressed)
        Global.event.task_range_progressed.connect(self._on_task_range_progressed)
        Global.event.interface_load_task_params.connect(self._on_interface_load_task_params)

        self.vl = QVBoxLayout()
        self.vl.setContentsMargins(0,0,0,0)

        self.setLayout(self.vl)
        self.setFixedWidth(290)

        self.tab = QTabWidget()
        self.vl.addWidget(self.tab)

        self.input_parameters = InputParameters()
        self.input_parameters.ranges_state_changed.connect(self._on_ranges_state_changed)
        self.tab.addTab(self.input_parameters, 'Parameters')

        self.import_parameters = ImportParameters()
        self.tab.addTab(self.import_parameters, 'Observation')

        control_buttons = QWidget()
        control_buttons.setLayout(QVBoxLayout())
        control_buttons.layout().setContentsMargins(0, 0, 0, 0)
        control_buttons.layout().setAlignment(Qt.AlignBottom)

        self._progress = QProgressBar()
        self._progress.setValue(0)
        self._progress.setTextVisible(True)
        self._progress.setAlignment(Qt.AlignCenter)
        self._progress.hide()
        control_buttons.layout().addWidget(self._progress)

        self._range_progress = QProgressBar()
        self._range_progress.setValue(0)
        self._range_progress.setTextVisible(True)
        self._range_progress.setAlignment(Qt.AlignCenter)
        self._range_progress.hide()
        control_buttons.layout().addWidget(self._range_progress)

        self._calculate = QPushButton('Calculate')
        self._calculate.clicked.connect(self._on_calculate)
        control_buttons.layout().addWidget(self._calculate)

        self._cancel = QPushButton('Cancel')
        self._cancel.hide()
        self._cancel.clicked.connect(self._on_cancel)
        control_buttons.layout().addWidget(self._cancel)

        self.vl.addWidget(control_buttons)

        if exists("./config/last-session.ini") :
            self.load_params("./config/last-session.ini")

    def _on_ranges_state_changed(self, parameters):
        Global.task_range().reset()

        if len(parameters):
            keys = parameters.keys()
            for key in parameters:
                Global.task_range().set_range(key, copy(parameters[key].range.values))

            self._calculate.setText('Calculate ' + str(Global.task_range()._total_count) + ' variations')
        else:
            self._calculate.setText('Calculate')

    def _on_calculate(self):
        self.import_parameters.import_observation()

        combination = Global.task_range().get_next_combination()

        Global.task().input.semi_major_axis = self.input_parameters.semi_major_axis.getValue()
        Global.task().input.star_radius = self.input_parameters.star_radius.getValue()
        Global.task().input.planet_radius = self.input_parameters.planet_radius.getValue()
        Global.task().input.star_temperature = self.input_parameters.star_temperature.getValue()
        Global.task().input.planet_temperature = self.input_parameters.planet_temperature.getValue()
        Global.task().input.darkening_law = self.input_parameters.darkening_law.value.itemData(self.input_parameters.darkening_law.value.currentIndex()).toString()
        Global.task().input.darkening_1 = self.input_parameters.darkening_coefficient_1.getValue()
        Global.task().input.darkening_2 = self.input_parameters.darkening_coefficient_2.getValue()
        Global.task().input.inclination = self.input_parameters.inclination.getValue()
        Global.task().input.phase_start = 0
        Global.task().input.phase_end = self.input_parameters.phase_end.getValue()
        Global.task().input.phase_step = self.input_parameters.phase_step.getValue()
        Global.task().input.precision = 10**self.input_parameters.integration_precision.getValue()

        if combination:
            for param in combination:
                setattr(Global.task().input, param[0], param[1])

        Global.task().start()

    def _on_task_range_progressed(self, progress):
        self._range_progress.setFormat( str(Global.task_range().completed_count()) + ' of ' + str(Global.task_range().total_count()))
        self._range_progress.setValue(math.ceil(((float(Global.task_range().completed_count()))/Global.task_range().total_count())*100))
        self._on_calculate()

    def _on_task_started(self, task):
        self._calculate.hide()
        self._progress.show()
        self._progress.setValue(0)
        self._cancel.show()
        self.tab.setDisabled(True)

        if Global.task_range().total_count():
            self._range_progress.show()
            if Global.task_range().completed_count() == 0:
                self._range_progress.setFormat('0 of ' + str(Global.task_range().total_count()))
                self._range_progress.setValue(0)

    def _on_task_progressed(self, task, progress):
        self._progress.setValue(progress)

    def _on_task_completed(self, task):
        if Global.task_range().total_count() and Global.task_range().completed_count():
            return

        self._calculate.show()
        self._progress.hide()
        self._progress.setValue(0)
        self._cancel.hide()
        self.tab.setDisabled(False)
        self._range_progress.hide()
        self._range_progress.setValue(0)

    def _on_cancel(self):
        Global.task().stop()

        self._calculate.show()
        self._progress.hide()
        self._progress.setValue(0)
        self._range_progress.hide()
        self._range_progress.setValue(0)
        self._cancel.hide()
        self.tab.setDisabled(False)

    def _on_interface_load_task_params(self, task):
        self.input_parameters.semi_major_axis.value.setValue(task.input.semi_major_axis)
        self.input_parameters.star_radius.value.setValue(task.input.star_radius)
        self.input_parameters.planet_radius.value.setValue(task.input.planet_radius)
        self.input_parameters.star_temperature.value.setValue(task.input.star_temperature)
        self.input_parameters.planet_temperature.value.setValue(task.input.planet_temperature)
        self.input_parameters.inclination.value.setValue(task.input.inclination)

        darkening_law_index = 0
        for item in DarkeningLaw.items:
            if item[1] == task.input.darkening_law:
                break
            darkening_law_index += 1

        self.input_parameters.darkening_law.value.setCurrentIndex(darkening_law_index)
        self.input_parameters.darkening_coefficient_1.value.setValue(task.input.darkening_1)
        self.input_parameters.darkening_coefficient_2.value.setValue(task.input.darkening_2)
        self.input_parameters.phase_end.value.setValue(task.input.phase_end)
        self.input_parameters.phase_step.value.setValue(task.input.phase_step)
        self.input_parameters.integration_precision.value.setValue(log10(task.input.precision))

        for parameter_name in copy(self.input_parameters.range_parameters):
            parameter = getattr(self.input_parameters, parameter_name)
            if parameter.range:
                parameter.range.set_active(False)

        self.repaint()

    def load_params(self, filename):
        config = ConfigParser()
        config.read(filename)

        self._normalize_config(config)

        # Input Parameters
        self._load_config_param(config, 'input', 'semi_major_axis')
        self._load_config_param(config, 'input', 'star_radius')
        self._load_config_param(config, 'input', 'planet_radius')
        self._load_config_param(config, 'input', 'star_temperature')
        self._load_config_param(config, 'input', 'planet_temperature')
        self._load_config_param(config, 'input', 'inclination')
        self._load_config_param(config, 'input', 'darkening_law')
        self._load_config_param(config, 'input', 'darkening_coefficient_1')
        self._load_config_param(config, 'input', 'darkening_coefficient_2')
        self._load_config_param(config, 'input', 'phase_end')
        self._load_config_param(config, 'input', 'phase_step')
        self._load_config_param(config, 'input', 'integration_precision')

        # Import Parameters
        if config.has_option('import', 'filename') and config.get('import', 'filename'):
            if '/data/' in config.get('import', 'filename') and config.get('import', 'filename').index('/data/') == 0:
                self.import_parameters.filename = os.getcwd().replace('\\', '/') + config.get('import', 'filename')
            else:
                self.import_parameters.filename = config.get('import', 'filename')

        self.import_parameters.update_file_label()

        if config.has_option('import', 'jd2phase') and config.getboolean('import', 'jd2phase') == True :
            self.import_parameters.hjd_to_phases.setCheckState(Qt.Checked)

        if config.has_option('import', 'jd2phase_tzero') :
            self.import_parameters.time_zero.setValue(config.getfloat('import', 'jd2phase_tzero'))

        if config.has_option('import', 'jd2phase_period') :
            self.import_parameters.period.setValue(config.getfloat('import', 'jd2phase_period'))

        if config.has_option('import', 'mag2flux') and config.getboolean('import', 'mag2flux') == True :
            self.import_parameters.magnitude_to_flux.setCheckState(Qt.Checked)

        if config.has_option('import', 'mag2flux_mag') :
            self.import_parameters.magnitude_max.setValue(config.getfloat('import', 'mag2flux_mag'))

        # Fixes painting bug with range buttons when loading new file
        # the active ranges stayed active even if they are inactive
        self.repaint()

    def _normalize_config(self, config):
        if config.has_option('input', 'darkening_1'):
            config.set('input', 'darkening_coefficient_1', config.get('input', 'darkening_1'))
            config.remove_option('input', 'darkening_1')

        if config.has_option('input', 'darkening_2'):
            config.set('input', 'darkening_coefficient_2', config.get('input', 'darkening_2'))
            config.remove_option('input', 'darkening_2')

        if config.has_option('input', 'precision'):
            config.set('input', 'integration_precision', config.get('input', 'precision'))
            config.remove_option('input', 'precision')

    def _load_config_param(self, config, section, name):
        param = getattr(self.input_parameters, name)

        if config.has_option(section, name):
            if type(param.value) is QComboBox:
                param.value.setCurrentIndex(config.getint(section, name))
            else:
                param.value.setValue(literal_eval(config.get(section, name)))

        if param.range:
            _from = _to = _step = _values = None
            _active = False

            if config.has_option(section, name + '_range_from'):
                _from = literal_eval(config.get(section, name + '_range_from'))

            if config.has_option(section, name + '_range_to'):
                _to = literal_eval(config.get(section, name + '_range_to'))

            if config.has_option(section, name + '_range_step'):
                _step = literal_eval(config.get(section, name + '_range_step'))

            if config.has_option(section, name + '_range_values'):
                _values = literal_eval(config.get(section, name + '_range_values'))

            if config.has_option(section, name + '_range_active'):
                _active = config.getboolean(section, name + '_range_active')

            if _values:
                param.range.set_range(_values)
            elif _from and _to and _step:
                param.range.set_range(_from, _to, _step)

            param.range.set_active(_active)

    def _save_config_param(self, config, section, name):
        param = getattr(self.input_parameters, name)

        if type(param.value) is QComboBox:
            config.set(section, name, param.value.currentIndex())
        else:
            config.set(section, name, param.getValue())

        if param.range:
            if param.range.range_from and param.range.range_to and param.range.range_step:
                config.set(section, name + '_range_from', param.range.range_from)
                config.set(section, name + '_range_to', param.range.range_to)
                config.set(section, name + '_range_step', param.range.range_step)
            elif param.range.values:
                config.set(section, name + '_range_values', param.range.values)

            if param.range.is_active():
                config.set(section, name + '_range_active', param.range.is_active())

    def save_params(self, filename):
        config = ConfigParser()
        config.add_section('input')

        # Input Parameters
        self._save_config_param(config, 'input', 'semi_major_axis')
        self._save_config_param(config, 'input', 'star_radius')
        self._save_config_param(config, 'input', 'planet_radius')
        self._save_config_param(config, 'input', 'star_temperature')
        self._save_config_param(config, 'input', 'planet_temperature')
        self._save_config_param(config, 'input', 'inclination')
        self._save_config_param(config, 'input', 'darkening_law')
        self._save_config_param(config, 'input', 'darkening_coefficient_1')
        self._save_config_param(config, 'input', 'darkening_coefficient_2')
        self._save_config_param(config, 'input', 'phase_end')
        self._save_config_param(config, 'input', 'phase_step')
        self._save_config_param(config, 'input', 'integration_precision')

        config.add_section('import')

        if os.getcwd().replace('\\', '/') in str(self.import_parameters.filename) and str(self.import_parameters.filename).index(os.getcwd().replace('\\', '/')) == 0 :
            save_file_path = str(self.import_parameters.filename).replace(os.getcwd().replace('\\', '/'), '')
        else:
            save_file_path = str(self.import_parameters.filename)

        config.set('import', 'filename', save_file_path)
        config.set('import', 'jd2phase', self.import_parameters.hjd_to_phases.checkState() == Qt.Checked)
        config.set('import', 'jd2phase_tzero', self.import_parameters.time_zero.value())
        config.set('import', 'jd2phase_period', self.import_parameters.period.value())
        config.set('import', 'mag2flux', self.import_parameters.magnitude_to_flux.checkState() == Qt.Checked)
        config.set('import', 'mag2flux_mag', self.import_parameters.magnitude_max.value())

        with open(filename, 'wb') as configfile:
            config.write(configfile)
        pass