Exemple #1
0
 def createTable(self, type_table, rows, list_of_komp):
     """
     Создание и заполнение таблицы
     :param type_table:
     :param row:
     :param list_komp:
     :param list_desc:
     :return:
     """
     if type_table == 'out':
         model = QStandardItemModel(rows, 2)
         list_horizontal = ['Код компетенции', 'Описание компетенции']
         model.setHorizontalHeaderLabels(list_horizontal)
         self.tableOut.setModel(model)
         self.tableOut.setColumnWidth(0, 110)
         self.tableOut.setColumnWidth(1, self.tableOut.width() - 130)
         for row in range(rows):
             for column in range(2):
                 index = model.index(row, column, QModelIndex())
                 model.setData(index, str(list_of_komp[row][column]).strip())
     else:
         model = QStandardItemModel(rows, 2)
         list_horizontal = ['Код компетенции', 'Описание компетенции']
         model.setHorizontalHeaderLabels(list_horizontal)
         self.tableIn.setModel(model)
         self.tableIn.setColumnWidth(0, 110)
         self.tableIn.setColumnWidth(1, self.tableIn.width() - 130)
         for row in range(rows):
             for column in range(2):
                 index = model.index(row, column, QModelIndex())
                 model.setData(index, str(list_of_komp[row][column]).strip())
Exemple #2
0
 def showSchema(self, table):
     """
     Public slot to show the schema of a table.
     
     @param table name of the table to be shown (string)
     """
     rec = self.connections.currentDatabase().record(table)
     model = QStandardItemModel(self.table)
     
     model.insertRows(0, rec.count())
     model.insertColumns(0, 7)
     
     model.setHeaderData(0, Qt.Horizontal, "Fieldname")
     model.setHeaderData(1, Qt.Horizontal, "Type")
     model.setHeaderData(2, Qt.Horizontal, "Length")
     model.setHeaderData(3, Qt.Horizontal, "Precision")
     model.setHeaderData(4, Qt.Horizontal, "Required")
     model.setHeaderData(5, Qt.Horizontal, "Auto Value")
     model.setHeaderData(6, Qt.Horizontal, "Default Value")
     
     for i in range(rec.count()):
         fld = rec.field(i)
         model.setData(model.index(i, 0), fld.name())
         if fld.typeID() == -1:
             model.setData(model.index(i, 1),
                           QVariant.typeToName(fld.type()))
         else:
             model.setData(
                 model.index(i, 1), "{0} ({1})".format(
                     QVariant.typeToName(fld.type()), fld.typeID()))
         if fld.length() < 0:
             model.setData(model.index(i, 2), "?")
         else:
             model.setData(model.index(i, 2), fld.length())
         if fld.precision() < 0:
             model.setData(model.index(i, 3), "?")
         else:
             model.setData(model.index(i, 3), fld.precision())
         if fld.requiredStatus() == -1:
             model.setData(model.index(i, 4), "?")
         else:
             model.setData(model.index(i, 4), bool(fld.requiredStatus()))
         model.setData(model.index(i, 5), fld.isAutoValue())
         model.setData(model.index(i, 6), fld.defaultValue())
     
     self.table.setModel(model)
     self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
     
     self.table.resizeColumnsToContents()
     
     self.updateActions()
Exemple #3
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        fileMenu = QMenu("&File", self)
        openAction = fileMenu.addAction("&Open...")
        openAction.setShortcut("Ctrl+O")
        saveAction = fileMenu.addAction("&Save As...")
        saveAction.setShortcut("Ctrl+S")
        quitAction = fileMenu.addAction("E&xit")
        quitAction.setShortcut("Ctrl+Q")

        self.setupModel()
        self.setupViews()

        openAction.triggered.connect(self.openFile)
        saveAction.triggered.connect(self.saveFile)
        quitAction.triggered.connect(QApplication.instance().quit)

        self.menuBar().addMenu(fileMenu)
        self.statusBar()

        self.openFile(':/Charts/qtdata.cht')

        self.setWindowTitle("Chart")
        self.resize(870, 550)

    def setupModel(self):
        self.model = QStandardItemModel(8, 2, self)
        self.model.setHeaderData(0, Qt.Horizontal, "Label")
        self.model.setHeaderData(1, Qt.Horizontal, "Quantity")

    def setupViews(self):
        splitter = QSplitter()
        table = QTableView()
        self.pieChart = PieView()
        splitter.addWidget(table)
        splitter.addWidget(self.pieChart)
        splitter.setStretchFactor(0, 0)
        splitter.setStretchFactor(1, 1)

        table.setModel(self.model)
        self.pieChart.setModel(self.model)

        self.selectionModel = QItemSelectionModel(self.model)
        table.setSelectionModel(self.selectionModel)
        self.pieChart.setSelectionModel(self.selectionModel)

        table.horizontalHeader().setStretchLastSection(True)

        self.setCentralWidget(splitter)

    def openFile(self, path=None):
        if not path:
            path, _ = QFileDialog.getOpenFileName(self, "Choose a data file",
                    '', '*.cht')

        if path:
            f = QFile(path)

            if f.open(QFile.ReadOnly | QFile.Text):
                stream = QTextStream(f)

                self.model.removeRows(0, self.model.rowCount(QModelIndex()),
                        QModelIndex())

                row = 0
                line = stream.readLine()
                while line:
                    self.model.insertRows(row, 1, QModelIndex())

                    pieces = line.split(',')
                    self.model.setData(self.model.index(row, 0, QModelIndex()),
                                pieces[0])
                    self.model.setData(self.model.index(row, 1, QModelIndex()),
                                float(pieces[1]))
                    self.model.setData(self.model.index(row, 0, QModelIndex()),
                                QColor(pieces[2]), Qt.DecorationRole)

                    row += 1
                    line = stream.readLine()

                f.close()
                self.statusBar().showMessage("Loaded %s" % path, 2000)

    def saveFile(self):
        fileName, _ = QFileDialog.getSaveFileName(self, "Save file as", '',
                '*.cht')

        if fileName:
            f = QFile(fileName)

            if f.open(QFile.WriteOnly | QFile.Text):
                for row in range(self.model.rowCount(QModelIndex())):
                    pieces = []

                    pieces.append(self.model.data(self.model.index(row, 0, QModelIndex()),
                            Qt.DisplayRole))
                    pieces.append(str(self.model.data(self.model.index(row, 1, QModelIndex()),
                            Qt.DisplayRole)))
                    pieces.append(self.model.data(self.model.index(row, 0, QModelIndex()),
                            Qt.DecorationRole).name())

                    f.write(QByteArray(','.join(pieces)))
                    f.write('\n')

            f.close()
            self.statusBar().showMessage("Saved %s" % fileName, 2000)
class IsosViewer(QMainWindow, mageiaSyncUI.Ui_mainWindow):
    #   Display the main window
    def __init__(self, parent=None):
        super(IsosViewer, self).__init__(parent)
        self.setupUi(self)
        self.connectActions()
        self.IprogressBar.setMinimum(0)
        self.IprogressBar.setMaximum(100)
        self.IprogressBar.setValue(0)
        self.IprogressBar.setEnabled(False)
        self.selectAllState=True
        self.stop.setEnabled(False)
        self.destination=''
        self.rsyncThread = mageiaSyncExt.syncThread(self)    # create a thread to launch rsync
        self.rsyncThread.progressSignal.connect(self.setProgress)
        self.rsyncThread.speedSignal.connect(self.setSpeed)
        self.rsyncThread.sizeSignal.connect(self.setSize)
        self.rsyncThread.remainSignal.connect(self.setRemain)
        self.rsyncThread.endSignal.connect(self.syncEnd)
        self.rsyncThread.lvM.connect(self.lvMessage)
        self.rsyncThread.checkSignal.connect(self.checks)
        self.checkThreads=[]    #   A list of thread for each iso

 #      Model for list view in a table
        self.model = QStandardItemModel(0, 6, self)
        headers=[self.tr("Directory"),self.tr("Name"),self.tr("Size"),self.tr("Date"),"SHA1","MD5"]
        i=0
        for label in headers:
            self.model.setHeaderData(i, QtCore.Qt.Horizontal,label )
            i+=1

#       settings for the list view
        self.localList.setModel(self.model)
        self.localList.setColumnWidth(0,220)
        self.localList.setColumnWidth(1,220)
        self.localList.horizontalHeader().setStretchLastSection(True)
        # settings for local iso names management
        self.localListNames=[]

    def multiSelect(self):
    #   allows to select multiple lines in remote ISOs list
        self.listIsos.setSelectionMode(2)

    def add(self, iso):
    #   Add an remote ISO in list
         self.listIsos.addItem(iso)

    def localAdd(self, path,iso,isoSize):
        #   Add an entry in local ISOs list, with indications about checking
        itemPath=QStandardItem(path)
        itemIso=QStandardItem(iso)
        if isoSize==0:
            itemSize=QStandardItem('--')
        else:
            formatedSize='{:n}'.format(isoSize).replace(","," ")
            itemSize=QStandardItem(formatedSize)
        itemSize.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
        itemDate=QStandardItem("--/--/--")
        itemDate.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
        itemCheck1=QStandardItem("--")
        itemCheck1.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
        itemCheck5=QStandardItem("--")
        itemCheck5.setTextAlignment(QtCore.Qt.AlignVCenter|QtCore.Qt.AlignHCenter)
        self.model.appendRow([itemPath,itemIso,itemSize,itemDate, itemCheck1, itemCheck5,])
        self.localListNames.append([path,iso])

    def setProgress(self, value):
        #   Update the progress bar
        self.IprogressBar.setValue(value)

    def setSpeed(self, value):
        #   Update the speed field
        self.speedLCD.display(value)

    def setSize(self, size):
        #   Update the size field
        self.Lsize.setText(size+self.tr(" bytes"))

    def setRemain(self,remainTime):
        content=QtCore.QTime.fromString(remainTime,"h:mm:ss")
        self.timeRemaining.setTime(content)

    def manualChecks(self):
        for iso in self.listIsos.selectedItems():
            path,name=iso.text().split('/')
            try:
                #   Look for ISO in local list
                item=self.model.findItems(name,QtCore.Qt.MatchExactly,1)[0]
            except:
                #   Remote ISO is not yet in local directory. We add it in localList and create the directory
                self.localAdd(path,name,0)
                basedir=QtCore.QDir(self.destination)
                basedir.mkdir(path)
                item=self.model.findItems(name,QtCore.Qt.MatchExactly,1)[0]
            row=self.model.indexFromItem(item).row()
            self.checks(row)

    def checks(self,isoIndex):
        #   processes a checking for each iso
        #   launches a thread for each iso
        newThread=mageiaSyncExt.checkThread(self)
        self.checkThreads.append(newThread)
        self.checkThreads[-1].setup(self.destination,
            self.model.data(self.model.index(isoIndex,0)) ,
            self.model.data(self.model.index(isoIndex,1)),
            isoIndex)
        self.checkThreads[-1].md5Signal.connect(self.md5Check)
        self.checkThreads[-1].sha1Signal.connect(self.sha1Check)
        self.checkThreads[-1].dateSignal.connect(self.dateCheck)
        self.checkThreads[-1].sizeFinalSignal.connect(self.sizeUpdate)
        self.checkThreads[-1].checkStartSignal.connect(self.checkStart)
        self.checkThreads[-1].start()

    def checkStart(self,isoIndex):
        #   the function indicates that checking is in progress
        #   the hundred contains index of the value to check, the minor value contains the row
        col=(int)(isoIndex/100)
        row=isoIndex-col*100
        self.model.setData(self.model.index(row, col, QtCore.QModelIndex()), self.tr("Checking"))

    def md5Check(self,check):
        if check>=128:
            val=self.tr("OK")
            row=check-128
        else:
            val=self.tr("Failed")
            row=check
        self.model.setData(self.model.index(row, 5, QtCore.QModelIndex()), val)

    def sha1Check(self,check):
        if check>=128:
            val=self.tr("OK")
            row=check-128
        else:
            val=self.tr("Failed")
            row=check
        self.model.setData(self.model.index(row, 4, QtCore.QModelIndex()), val)

    def dateCheck(self,check):
        if check>=128:
            val=self.tr("OK")
            row=check-128
        else:
            val=self.tr("Failed")
            row=check
        self.model.setData(self.model.index(row, 3, QtCore.QModelIndex()), val)

    def sizeUpdate(self,signal,isoSize):
        col=(int)(signal/100)
        row=signal-col*100
        self.model.setData(self.model.index(row, col, QtCore.QModelIndex()), isoSize)

    def syncEnd(self, rc):
        if rc==1:
            self.lvMessage(self.tr("Command rsync not found"))
        elif rc==2:
            self.lvMessage(self.tr("Error in rsync parameters"))
        elif rc==3:
            self.lvMessage(self.tr("Unknown error in rsync"))
        self.IprogressBar.setEnabled(False)
        self.syncGo.setEnabled(True)
        self.listIsos.setEnabled(True)
        self.selectAll.setEnabled(True)
        self.stop.setEnabled(False)

    def prefsInit(self):
    #   Load the parameters at first
        params=QtCore.QSettings("Mageia","mageiaSync")
        paramRelease=""
        try:
            paramRelease=params.value("release", type="QString")
            #   the parameters already initialised?
        except:
            pass
        if paramRelease =="":
            # Values are not yet set
            self.pd0=prefsDialog0()
            self.pd0.user.setFocus()
            answer=self.pd0.exec_()
            if answer:
                #   Update params
                self.user=self.pd0.user.text()
                self.password=self.pd0.password.text()
                self.location=self.pd0.location.text()
                params=QtCore.QSettings("Mageia","mageiaSync")
                params.setValue("user",self.user)
                params.setValue("password",self.password)
                params.setValue("location",self.location)
            else:
                pass
#                answer=QDialogButtonBox(QDialogButtonBox.Ok)
                # the user must set values or default values
            self.pd0.close()
            self.pd=prefsDialog()
            if self.password !="":
                code,list=mageiaSyncExt.findRelease('rsync://'+self.user+'@bcd.mageia.org/isos/',self.password)
                if code==0:
                    for item in list:
                        self.pd.release.addItem(item)
            self.pd.password.setText(self.password)
            self.pd.user.setText(self.user)
            self.pd.location.setText(self.location)
            self.pd.selectDest.setText(QtCore.QDir.currentPath())
            self.pd.release.setFocus()
            answer=self.pd.exec_()
            if answer:
                #   Update params
                self.user=self.pd.user.text()
                self.password=self.pd.password.text()
                self.location=self.pd.location.text()
                params=QtCore.QSettings("Mageia","mageiaSync")
                self.release= self.pd.release.currentText()
                self.destination=self.pd.selectDest.text()
                self.bwl=self.pd.bwl.value()
                params.setValue("release", self.release)
                params.setValue("user",self.user)
                params.setValue("password",self.password)
                params.setValue("location",self.location)
                params.setValue("destination",self.destination)
                params.setValue("bwl",str(self.bwl))
            else:
                pass
#                answer=QDialogButtonBox(QDialogButtonBox.Ok)
                print(self.tr("the user must set values or default values"))
            self.pd.close()
        else:
            self.release=params.value("release", type="QString")
            self.user=params.value("user", type="QString")
            self.location=params.value("location", type="QString")
            self.password=params.value("password", type="QString")
            self.destination=params.value("destination", type="QString")
            self.bwl=params.value("bwl",type=int)
        self.localDirLabel.setText(self.tr("Local directory: ")+self.destination)
        if self.location !="":
            self.remoteDirLabel.setText(self.tr("Remote directory: ")+self.location)

    def selectDestination(self):
        #   dialog box to select the destination (local directory)
        directory = QFileDialog.getExistingDirectory(self, self.tr('Select a directory'),'~/')
        isosSync.destination = directory
        self.pd.selectDest.setText(isosSync.destination)


    def selectAllIsos(self):
        #   Select or unselect the ISOs in remote list
        if self.selectAllState :
            for i in range(self.listIsos.count()):
                self.listIsos.item(i).setSelected(True)
            self.selectAll.setText(self.tr("Unselect &All"))
        else:
            for i in range(self.listIsos.count()):
                self.listIsos.item(i).setSelected(False)
            self.selectAll.setText(self.tr("Select &All"))
        self.selectAllState=not self.selectAllState

    def connectActions(self):
        self.actionQuit.triggered.connect(app.quit)
        self.quit.clicked.connect(app.quit)
        self.actionRename.triggered.connect(self.rename)
        self.actionUpdate.triggered.connect(self.updateList)
        self.actionCheck.triggered.connect(self.manualChecks)
        self.actionPreferences.triggered.connect(self.prefs)
        self.syncGo.clicked.connect(self.launchSync)
        self.selectAll.clicked.connect(self.selectAllIsos)

    def updateList(self):
        # From the menu entry
        self.lw = LogWindow()
        self.lw.show()
        self.listIsos.clear()
        self.model.removeRows(0,self.model.rowCount())
        if self.location  == "" :
            self.nameWithPath='rsync://'+self.user+'@bcd.mageia.org/isos/'+self.release+'/'
#            print self.nameWithPath
        else:
            self.nameWithPath=self.location+'/'
        self.lvMessage(self.tr("Source: ")+self.nameWithPath)
        self.fillList = mageiaSyncExt.findIsos()
        self.fillList.setup(self.nameWithPath, self.password,self.destination)
        self.fillList.endSignal.connect(self.closeFill)
        self.fillList.start()
        # Reset the button
        self.selectAll.setText(self.tr("Select &All"))
        self.selectAllState=True

    def lvMessage( self,message):
        #   Add a line in the logview
        self.lvText.append(message)

    def renameDir(self):
        #   Choose the directory where isos are stored
        directory = QFileDialog.getExistingDirectory(self, self.tr('Select a directory'),self.destination)
        self.rd.chooseDir.setText(directory)

    def rename(self):
        #   rename old isos and directories to a new release
        self.rd=renameDialog()
        loc=[]
        loc=self.location.split('/')
        self.rd.oldRelease.setText(loc[-1])
        self.rd.chooseDir.setText(self.destination)
        answer=self.rd.exec_()
        if answer:
            returnMsg=mageiaSyncExt.rename(self.rd.chooseDir.text(),self.rd.oldRelease.text(),str(self.rd.newRelease.text()))
            self.lvMessage(returnMsg)
        self.rd.close()

    def prefs(self):
        # From the menu entry
        self.pd=prefsDialog()
        self.pd.release.addItem(self.release)
        self.pd.password.setText(self.password)
        self.pd.user.setText(self.user)
        self.pd.location.setText(self.location)
        self.pd.selectDest.setText(self.destination)
        self.pd.bwl.setValue(self.bwl)
        params=QtCore.QSettings("Mageia","mageiaSync")
        answer=self.pd.exec_()
        if answer:
            params.setValue("release", self.pd.release.currentText())
            params.setValue("user",self.pd.user.text())
            params.setValue("password",self.pd.password.text())
            params.setValue("location",self.pd.location.text())
            params.setValue("destination",self.pd.selectDest.text())
            params.setValue("bwl",str(self.pd.bwl.value()))
        self.prefsInit()
        self.pd.close()


    def launchSync(self):
        self.IprogressBar.setEnabled(True)
        self.stop.setEnabled(True)
        self.syncGo.setEnabled(False)
        self.listIsos.setEnabled(False)
        self.selectAll.setEnabled(False)
        # Connect the button Stop
        self.stop.clicked.connect(self.stopSync)
        self.rsyncThread.params(self.password, self.bwl)
        for iso in self.listIsos.selectedItems():
            path,name=iso.text().split('/')
            try:
                #   Look for ISO in local list
                item=self.model.findItems(name,QtCore.Qt.MatchExactly,1)[0]
            except:
                #   Remote ISO is not yet in local directory. We add it in localList and create the directory
                self.localAdd(path,name,0)
                basedir=QtCore.QDir(self.destination)
                basedir.mkdir(path)
                item=self.model.findItems(name,QtCore.Qt.MatchExactly,1)[0]
            row=self.model.indexFromItem(item).row()
            if self.location  == "" :
                self.nameWithPath='rsync://'+self.user+'@bcd.mageia.org/isos/'+self.release+'/'+path
            else:
                self.nameWithPath=self.location+path
            if (not str(path).endswith('/')):
                    self.nameWithPath+='/'
            self.rsyncThread.setup(self.nameWithPath, self.destination+'/'+path+'/',row)
        self.rsyncThread.start()             # start the thread
        # Pour les tests uniquement
            #rsync://[email protected]/isos/$release/
        #self.nameWithPath='rsync://ftp5.gwdg.de/pub/linux/mageia/iso/4.1/Mageia-4.1-LiveCD-GNOME-en-i586-CD/'

    def closeFill(self,code):
        if code==0: #   list returned
            list=self.fillList.getList()
            for iso in list:
                self.add(iso)
        elif code==1:
            self.lvMessage(self.tr("Command rsync not found"))
        elif code==2:
            self.lvMessage(self.tr("Error in rsync parameters"))
        elif code==3:
            self.lvMessage(self.tr("Unknown error in rsync"))
        list=self.fillList.getList()

        list=self.fillList.getLocal()
        for path,iso,isoSize in list:
            self.localAdd(path,iso, isoSize)
        self.fillList.quit()
        self.lw.hide()

    def stopSync(self):
        self.rsyncThread.stop()
        self.IprogressBar.setEnabled(False)
        self.stop.setEnabled(False)
        self.syncGo.setEnabled(True)
        self.listIsos.setEnabled(True)
        self.selectAll.setEnabled(True)


    def main(self):
        self.show()
        #   Load or look for intitial parameters
        self.prefsInit()
        # look for Isos list and add it to the isoSync list. Update preferences
        self.updateList()
        self.multiSelect()

    def close(self):
        self.rsyncThread.stop()
        exit(0)
Exemple #5
0
class MDIHistory(QWidget, _HalWidgetBase):
    def __init__(self, parent=None):
        super(MDIHistory, self).__init__(parent)
        self.setMinimumSize(QSize(200, 150))    
        self.setWindowTitle("PyQt5 editor test example") 

        lay = QVBoxLayout()
        lay.setContentsMargins(0,0,0,0)
        self.setLayout(lay)

        self.list = QListView()
        self.list.setEditTriggers(QListView.NoEditTriggers)
        self.list.activated.connect(self.activated)
        self.list.setAlternatingRowColors(True)
        self.list.selectionChanged = self.selectionChanged
        self.model = QStandardItemModel(self.list)

        self.MDILine = MDILine()
        self.MDILine.soft_keyboard = False
        self.MDILine.line_up = self.line_up
        self.MDILine.line_down = self.line_down

        STATUS.connect('reload-mdi-history', self.reload)

        # add widgets
        lay.addWidget(self.list)
        lay.addWidget(self.MDILine)

        self.fp = os.path.expanduser(INFO.MDI_HISTORY_PATH)
        try:
            open(self.fp, 'r')
        except:
            open(self.fp, 'a+')
            LOG.debug('MDI History file created: {}'.format(self.fp))
        self.reload()
        self.select_row('last')

    def _hal_init(self):
        STATUS.connect('state-off', lambda w: self.setEnabled(False))
        STATUS.connect('state-estop', lambda w: self.setEnabled(False))
        STATUS.connect('interp-idle', lambda w: self.setEnabled(STATUS.machine_is_on()
                                                                and (STATUS.is_all_homed()
                                                                or INFO.NO_HOME_REQUIRED)))
        STATUS.connect('interp-run', lambda w: self.setEnabled(not STATUS.is_auto_mode()))
        STATUS.connect('all-homed', lambda w: self.setEnabled(STATUS.machine_is_on()))

    def reload(self, w=None ):
        self.model.clear()
        try:
            with open(self.fp,'r') as inputfile:
                for line in inputfile:
                    line = line.rstrip('\n')
                    item = QStandardItem(line)
                    self.model.appendRow(item)
            self.list.setModel(self.model)
            self.list.scrollToBottom()
            if self.MDILine.hasFocus():
                self.select_row('last')
        except:
            LOG.debug('File path is not valid: {}'.format(fp))

    def selectionChanged(self,old, new):
        cmd = self.getSelected()
        self.MDILine.setText(cmd)
        selectionModel = self.list.selectionModel()
        if selectionModel.hasSelection():
            self.row = selectionModel.currentIndex().row()

    def getSelected(self):
        selected_indexes = self.list.selectedIndexes()
        selected_rows = [item.row() for item in selected_indexes]
        # iterates each selected row in descending order
        for selected_row in sorted(selected_rows, reverse=True):
            text = self.model.item(selected_row).text()
            return text

    def activated(self):
        cmd = self.getSelected()
        self.MDILine.setText(cmd)
        self.MDILine.submit()
        self.select_row('down')

    def select_row(self, style):
        selectionModel = self.list.selectionModel()
        parent = QModelIndex()
        self.rows = self.model.rowCount(parent) - 1
        if style == 'last':
            self.row = self.rows
        elif style == 'up':
            if self.row > 0:
                self.row -= 1
            else:
                self.row = self.rows
        elif style == 'down':
            if self.row < self.rows:
                self.row += 1
            else:
                self.row = 0
        else:
            return
        top = self.model.index(self.row, 0, parent)
        bottom = self.model.index(self.row, 0, parent)
        selectionModel.setCurrentIndex(top, QItemSelectionModel.Select | QItemSelectionModel.Rows)
        selection = QItemSelection(top, top)
        selectionModel.clearSelection()
        selectionModel.select(selection, QItemSelectionModel.Select)

    def line_up(self):
        self.select_row('up')

    def line_down(self):
        self.select_row('down')

    #########################################################################
    # This is how designer can interact with our widget properties.
    # designer will show the pyqtProperty properties in the editor
    # it will use the get set and reset calls to do those actions
    #########################################################################

    def set_soft_keyboard(self, data):
        self.MDILine.soft_keyboard = data
    def get_soft_keyboard(self):
        return self.MDILine.soft_keyboard
    def reset_soft_keyboard(self):
        self.MDILine.soft_keyboard = False

    # designer will show these properties in this order:
    soft_keyboard_option = pyqtProperty(bool, get_soft_keyboard, set_soft_keyboard, reset_soft_keyboard)
Exemple #6
0
class MassTabSelectorGUI(QDockWidget):

    """
    classdocs
    """
    masstabViewRaisedSignal = pyqtSignal(object)

    """ constructor """

    def __init__(self, parent=None):
        super(MassTabSelectorGUI, self).__init__(parent)
        self.ui = Ui_DockWidget_MassTabSelector()
        self.ui.setupUi(self)

    def setup(self, analysis):
        self.ana = analysis
        self.__connect_events()

    def __connect_events(self):
        self.model = QStandardItemModel()
        self.mass_list = []
        for i in range(10):
            mass = 184 + i
            self.mass_list.append(str(mass))
        for i in range(10):
            mass = 209 + i
            self.mass_list.append(str(mass))
        for i in range(10):
            mass = 273.3 + i
            self.mass_list.append(str(mass))
        for i in range(10):
            mass = 294 + i
            self.mass_list.append(str(mass))
        for mass in self.mass_list:
            item = QStandardItem(mass)
            item.setCheckable(True)
            item.setEditable(True)
            self.model.appendRow(item)
        self.view = self.ui.listView_Mass
        self.view.setModel(self.model)
        # changes in one item, don't know which one
        self.model.itemChanged.connect(self.change_list)
        # changes in button
        self.ui.pushButton_ChangeList.clicked.connect(self.emit_list_signal)
        # get peaks found and update automatically the mass list
        self.ana.masstabSelectorRaisedSignal.connect(self.update_list_view)

    def update_list_view(self, xind):
        self.mass_list = []
        for i in range(len(xind)):
            m = "{:.1f}".format(float(xind[i]))
            self.mass_list.append(str(m))
        self.model.clear()
        self.model = QStandardItemModel()

        for mass in self.mass_list:
            item = QStandardItem(mass)
            item.setCheckable(True)
            item.setEditable(True)
            item.setCheckState(Qt.Checked)
            self.model.appendRow(item)
        self.view = self.ui.listView_Mass
        self.view.setModel(self.model)
        # changes in one item, don't know which one
        self.model.itemChanged.connect(self.change_list)

    def change_list(self):
        log.debug("event from %s", self.sender())
        self.oneIsChecked = False
        self.mass_list = []
        count = self.model.rowCount()
        for i in range(count):
            checked = self.model.item(i).checkState()
            if checked:
                mass_name = self.model.data(self.model.index(i, 0))
                self.mass_list.append(mass_name)
                self.oneIsChecked = True

    def emit_list_signal(self):
        log.debug("event from %s", self.sender())
        self.change_list()
        if self.oneIsChecked:
            self.masstabViewRaisedSignal.emit(self.mass_list)
class RefsWidget(QObject):

    error = pyqtSignal(Exception)
    reference_changed = pyqtSignal(Node)

    def __init__(self, view):
        self.view = view
        QObject.__init__(self, view)
        self.model = QStandardItemModel()

        delegate = MyDelegate(self.view, self)
        delegate.error.connect(self.error.emit)
        delegate.reference_changed.connect(self.reference_changed.emit)
        self.view.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.view.setModel(self.model)
        self.view.setItemDelegate(delegate)
        self.settings = QSettings()
        self.model.setHorizontalHeaderLabels(['ReferenceType', 'NodeId', "BrowseName", "TypeDefinition"])
        state = self.settings.value("WindowState/refs_widget_state", None)
        if state is not None:
            self.view.horizontalHeader().restoreState(state)
        self.view.horizontalHeader().setSectionResizeMode(0)
        self.view.horizontalHeader().setStretchLastSection(True)
        self.node = None

        self.reloadAction = QAction("Reload", self.model)
        self.reloadAction.triggered.connect(self.reload)
        self.addRefAction = QAction("Add Reference", self.model)
        self.addRefAction.triggered.connect(self.add_ref)
        self.removeRefAction = QAction("Remove Reference", self.model)
        self.removeRefAction.triggered.connect(self.remove_ref)

        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.showContextMenu)
        self._contextMenu = QMenu()
        self._contextMenu.addAction(self.reloadAction)
        self._contextMenu.addSeparator()
        self._contextMenu.addAction(self.addRefAction)
        self._contextMenu.addAction(self.removeRefAction)

    def showContextMenu(self, position):
        if not self.node:
            return
        self.removeRefAction.setEnabled(False)
        idx = self.view.currentIndex()
        if idx.isValid():
            self.removeRefAction.setEnabled(True)
        self._contextMenu.exec_(self.view.viewport().mapToGlobal(position))

    def clear(self):
        # remove all rows but not header!!
        self.model.removeRows(0, self.model.rowCount())
        self.node = None

    def _make_default_ref(self):
        #FIXME: remeber last choosen values or use values that make sense
        ref = ua.ReferenceDescription()
        return ref

    @trycatchslot
    def add_ref(self):
        ref = self._make_default_ref()
        logger.info("Adding ref: %s", ref)
        self._add_ref_row(ref)
        idx = self.model.index(self.model.rowCount() - 1, 0)
        self.view.setCurrentIndex(idx)
        #self.view.edit(idx)

    @trycatchslot
    def reload(self):
        node = self.node
        self.clear()
        self.show_refs(node)

    @trycatchslot
    def remove_ref(self):
        idx = self.view.currentIndex()
        if not idx.isValid():
            logger.warning("No valid reference selected to remove")
        idx = idx.sibling(idx.row(), 0)
        item = self.model.itemFromIndex(idx)
        ref = item.data(Qt.UserRole)
        self.do_remove_ref(ref)
        self.reload()
    
    def do_remove_ref(self, ref, check=True):
        logger.info("Removing: %s", ref)
        it = ua.DeleteReferencesItem()
        it.SourceNodeId = self.node.nodeid
        it.ReferenceTypeId = ref.ReferenceTypeId
        it.IsForward = ref.IsForward
        it.TargetNodeId = ref.NodeId
        it.DeleteBidirectional = False
        #param = ua.DeleteReferencesParameters()
        #param.ReferencesToDelete.append(it)
        results = self.node.server.delete_references([it])
        logger.info("Remove result: %s", results[0]) 
        if check:
            results[0].check()

    def save_state(self):
        self.settings.setValue("WindowState/refs_widget_state", self.view.horizontalHeader().saveState())

    def show_refs(self, node):
        self.clear()
        self.node = node
        self._show_refs(node)

    def _show_refs(self, node):
        try:
            refs = node.get_children_descriptions(refs=ua.ObjectIds.References)
        except Exception as ex:
            self.error.emit(ex)
            raise
        for ref in refs:
            self._add_ref_row(ref)

    def _add_ref_row(self, ref):
        if ref.ReferenceTypeId.Identifier in ua.ObjectIdNames:
            typename = ua.ObjectIdNames[ref.ReferenceTypeId.Identifier]
        else:
            typename = str(ref.ReferenceTypeId)
        if ref.NodeId.NamespaceIndex == 0 and ref.NodeId.Identifier in ua.ObjectIdNames:
            nodeid = ua.ObjectIdNames[ref.NodeId.Identifier]
        else:
            nodeid = ref.NodeId.to_string()
        if ref.TypeDefinition.Identifier in ua.ObjectIdNames:
            typedef = ua.ObjectIdNames[ref.TypeDefinition.Identifier]
        else:
            typedef = ref.TypeDefinition.to_string()
        titem = QStandardItem(typename)
        titem.setData(ref, Qt.UserRole)
        self.model.appendRow([
            titem,
            QStandardItem(nodeid),
            QStandardItem(ref.BrowseName.to_string()),
            QStandardItem(typedef)
        ])
Exemple #8
0
class SubtitleEditor(SubTab):
    def __init__(self, filePath, subtitleData, parent = None):
        name = os.path.split(filePath)[1]
        super(SubtitleEditor, self).__init__(name, parent)
        self.__initWidgets()
        self.__initContextMenu()

        self._settings = SubSettings()

        self._filePath = filePath
        self._movieFilePath = None
        self._subtitleData = subtitleData

        self.refreshSubtitles()

        # Some signals
        self._subtitleData.fileChanged.connect(self.fileChanged)
        self._subtitleData.subtitlesAdded.connect(self._subtitlesAdded)
        self._subtitleData.subtitlesRemoved.connect(self._subtitlesRemoved)
        self._subtitleData.subtitlesChanged.connect(self._subtitlesChanged)
        self._model.itemChanged.connect(self._subtitleEdited)
        self.customContextMenuRequested.connect(self.showContextMenu)

    def __initWidgets(self):
        minimalSizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        # List of subtitles
        subListDelegate = SubListItemDelegate()
        self._model = QStandardItemModel(0, 3, self)
        self._model.setHorizontalHeaderLabels([_("Begin"), _("End"), _("Subtitle")])
        self._subList = QTableView(self)
        self._subList.setModel(self._model)
        self._subList.setItemDelegateForColumn(0, subListDelegate)
        self._subList.setItemDelegateForColumn(1, subListDelegate)
        self._subList.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)

        self._searchBar = SearchBar(self)
        self._searchBar.hide()

        # Top toolbar
        toolbar = QHBoxLayout()
        toolbar.setAlignment(Qt.AlignLeft)
        #toolbar.addWidget(someWidget....)
        toolbar.addStretch(1)

        # Main layout
        grid = QGridLayout()
        grid.setSpacing(10)
        grid.setContentsMargins(0, 3, 0, 0)
        grid.addLayout(toolbar, 0, 0, 1, 1) # stretch to the right
        grid.addWidget(self._subList, 1, 0)
        grid.addWidget(self._searchBar, 2, 0)
        self.setLayout(grid)

    def __initContextMenu(self):
        self._contextMenu = QMenu(self)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        af = ActionFactory(self)

        insertSub = af.create(title = _("&Insert subtitle"), icon = "list-add",
            connection = self.insertNewSubtitle)
        self._contextMenu.addAction(insertSub)

        insertSub = af.create(title = _("&Add subtitle"), icon = "list-add",
            connection = self.addNewSubtitle)
        self._contextMenu.addAction(insertSub)

        removeSub = af.create(title = _("&Remove subtitles"), icon = "list-remove",
            connection = self.removeSelectedSubtitles)
        self._contextMenu.addAction(removeSub)

    def _changeRowBackground(self, rowNo, bg):
        with DisableSignalling(self._model.itemChanged, self._subtitleEdited):
            for columnNo in range(self._model.columnCount()):
                item = self._model.item(rowNo, columnNo)
                item.setBackground(bg)

    def _changeItemData(self, item, val, role):
        with DisableSignalling(self._model.itemChanged, self._subtitleEdited):
            item.setData(val, role)

    def _handleIncorrectItem(self, item):
        with DisableSignalling(self._model.itemChanged, self._subtitleEdited):
            item.setData(False, CustomDataRoles.ErrorFlagRole)

        bg = item.background()
        rowNo = item.row()
        self._changeRowBackground(rowNo, Qt.red)
        QTimer.singleShot(600, lambda rowNo=rowNo, bg=bg: self._changeRowBackground(rowNo, bg))

    def _subtitleEdited(self, item):
        modelIndex = item.index()
        column = modelIndex.column()
        subNo = modelIndex.row()

        errorFlag = item.data(CustomDataRoles.ErrorFlagRole)
        if errorFlag is True:
            self._handleIncorrectItem(item)
        else:
            # TODO: timeStart and timeEnd might be displayed in a frame format in a bright future.
            # Check it and create FrameTime properly in that case.
            # TODO: Maybe add column numbers to some kind of enum to avoid magic numbers?
            oldSubtitle = self.subtitles[subNo]
            newSubtitle = oldSubtitle.clone()
            if 0 == column:
                timeStart = item.data(CustomDataRoles.FrameTimeRole)
                newSubtitle.change(start = timeStart)
            elif 1 == column:
                timeEnd = item.data(CustomDataRoles.FrameTimeRole)
                newSubtitle.change(end = timeEnd)
            elif 2 == column:
                newSubtitle.change(text = item.text())
            command = ChangeSubtitle(self.filePath, oldSubtitle, newSubtitle, subNo)
            self._subtitleData.execute(command)

    def _subtitlesAdded(self, path, subNos):
        if path != self.filePath:
            return

        subtitles = self.subtitles
        for subNo in subNos:
            row = createRow(subtitles[subNo])
            self._model.insertRow(subNo, row)

    def _subtitlesRemoved(self, path, subNos):
        if path != self.filePath:
            return

        for subNo in subNos:
            self._model.removeRow(subNo)

    def _subtitlesChanged(self, path, subNos):
        if path != self.filePath:
            return

        for subNo in subNos:
            self.refreshSubtitle(subNo)

    def _createNewSubtitle(self, data, subNo):
        fps = data.fps # data is passed to avoid unnecessary copies
        minFrameTime = FrameTime(fps, frames = 1)

        # calculate correct minimum subtitle start time
        if subNo > 0:
            timeStart = data.subtitles[subNo - 1].end + minFrameTime
        else:
            timeStart = FrameTime(fps, frames = 0)

        # calculate correct maximum subtitle end time
        if subNo < data.subtitles.size():
            try:
                timeEnd = data.subtitles[subNo].start - minFrameTime
            except SubException:
                timeEnd = FrameTime(fps, frames = 0)
        else:
            timeEnd = timeStart + FrameTime(fps, frames = 50)

        # add subtitle to DataModel
        sub = Subtitle(timeStart, timeEnd, "")
        command = AddSubtitle(self.filePath, subNo, sub)
        with DisableSignalling(self._subtitleData.subtitlesAdded, self._subtitlesAdded):
            self._subtitleData.execute(command)

        # create subtitle graphical representation in editor sub list
        row = createRow(sub)
        self._model.insertRow(subNo, row)
        index = self._model.index(subNo, 2)
        self._subList.clearSelection()
        self._subList.setCurrentIndex(index)
        self._subList.edit(index)

    def addNewSubtitle(self):
        data = self.data
        subNo = data.subtitles.size()
        indices = self._subList.selectedIndexes()
        if len(indices) > 0:
            rows = [index.row() for index in indices]
            subNo = max(rows) + 1
        self._createNewSubtitle(data, subNo)

    def insertNewSubtitle(self):
        data = self.data
        subNo = 0
        indices = self._subList.selectedIndexes()
        if len(indices) > 0:
            rows = [index.row() for index in indices]
            subNo = max(rows)
        self._createNewSubtitle(data, subNo)

    def removeSelectedSubtitles(self):
        indices = self._subList.selectedIndexes()
        if len(indices) > 0:
            rows = list(set([index.row() for index in indices]))
            command = RemoveSubtitles(self.filePath, rows)
            self._subtitleData.execute(command)
            if self._model.rowCount() > rows[-1]:
                self._subList.selectRow(rows[-1])
            else:
                self._subList.selectRow(self._model.rowCount() - 1)

    def highlight(self):
        self._searchBar.show()
        self._searchBar.highlight()

    def showContextMenu(self):
        self._contextMenu.exec(QCursor.pos())

    def changeInputEncoding(self, encoding):
        data = self._subtitleData.data(self.filePath)
        if encoding != data.inputEncoding:
            try:
                data.encode(encoding)
            except UnicodeDecodeError:
                message = QMessageBox(
                    QMessageBox.Warning,
                    _("Decoding error"),
                    _("Cannot decode subtitles to '%s' encoding.\nPlease try different encoding.") % encoding,
                    QMessageBox.Ok, self
                )
                message.exec()
            except LookupError:
                message = QMessageBox(QMessageBox.Warning,
                    _("Unknown encoding"), _("Unknown encoding: '%s'") % encoding,
                    QMessageBox.Ok, self
                )
                message.exec()
            else:
                # TODO: outputEncoding
                command = ChangeData(self.filePath, data, _("Input encoding: %s") % encoding)
                self._subtitleData.execute(command)

    def changeOutputEncoding(self, encoding):
        data = self._subtitleData.data(self.filePath)
        if encoding != data.outputEncoding:
            data.outputEncoding = encoding
            command = ChangeData(self.filePath, data, _("Output encoding: %s") % encoding)
            self._subtitleData.execute(command)

    def changeSubFormat(self, fmt):
        data = self._subtitleData.data(self.filePath)
        if data.outputFormat != fmt:
            data.outputFormat = fmt
            command = ChangeData(self.filePath, data)
            self._subtitleData.execute(command)

    def changeFps(self, fps):
        data = self.data
        if data.fps != fps:
            data.subtitles.changeFps(fps)
            data.fps = fps
            command = ChangeData(self.filePath, data, _("FPS: %s") % fps)
            self._subtitleData.execute(command)

    def changeVideoPath(self, path):
        data = self.data
        if data.videoPath != path:
            data.videoPath = path
            command = ChangeData(self.filePath, data, _("Video path: %s") % path)
            self._subtitleData.execute(command)

    def offset(self, seconds):
        data = self.data
        fps = data.subtitles.fps
        if fps is None:
            log.error(_("No FPS for '%s' (empty subtitles)." % self.filePath))
            return
        ft = FrameTime(data.subtitles.fps, seconds=seconds)
        data.subtitles.offset(ft)
        command = ChangeData(self.filePath, data,
                             _("Offset by: %s") % ft.toStr())
        self._subtitleData.execute(command)

    def detectFps(self):
        data = self.data
        if data.videoPath is not None:
            fpsInfo = File.detectFpsFromMovie(data.videoPath)
            if data.videoPath != fpsInfo.videoPath or data.fps != fpsInfo.fps:
                data.videoPath = fpsInfo.videoPath
                data.subtitles.changeFps(fpsInfo.fps)
                data.fps = fpsInfo.fps
                command = ChangeData(self.filePath, data, _("Detected FPS: %s") % data.fps)
                self._subtitleData.execute(command)

    def fileChanged(self, filePath):
        if filePath == self._filePath:
            self.refreshSubtitles()

    def refreshSubtitle(self, subNo):
        sub = self.subtitles[subNo]
        self._model.removeRow(subNo)
        self._model.insertRow(subNo, createRow(sub))

    def refreshSubtitles(self):
        self._model.removeRows(0, self._model.rowCount())
        for sub in self.subtitles:
            self._model.appendRow(createRow(sub))

    def updateTab(self):
        self.refreshSubtitles()

    def selectedSubtitles(self):
        rows = self.selectedRows()
        subtitleList = [self.subtitles[row] for row in rows]
        return subtitleList

    def selectedRows(self):
        indices = self._subList.selectedIndexes()
        # unique list
        rows = list(set([index.row() for index in indices]))
        rows.sort()
        return rows

    def selectRow(self, row):
        self._subList.selectRow(row)

    @property
    def filePath(self):
        return self._filePath

    @property
    def movieFilePath(self):
        return self._movieFilePath

    @property
    def data(self):
        return self._subtitleData.data(self.filePath)

    @property
    def subtitles(self):
        return self.data.subtitles

    @property
    def history(self):
        return self._subtitleData.history(self.filePath)

    @property
    def inputEncoding(self):
        return self.data.inputEncoding

    @property
    def outputEncoding(self):
        return self.data.outputEncoding

    @property
    def outputFormat(self):
        return self.data.outputFormat
class AddressList(MyTreeView):
    class Columns(IntEnum):
        TYPE = 0
        ADDRESS = 1
        LABEL = 2
        COIN_BALANCE = 3
        FIAT_BALANCE = 4
        NUM_TXS = 5

    filter_columns = [
        Columns.TYPE, Columns.ADDRESS, Columns.LABEL, Columns.COIN_BALANCE
    ]

    ROLE_SORT_ORDER = Qt.UserRole + 1000

    def __init__(self, parent):
        super().__init__(parent,
                         self.create_menu,
                         stretch_column=self.Columns.LABEL)
        self.wallet = self.parent.wallet
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSortingEnabled(True)
        self.show_change = AddressTypeFilter.ALL  # type: AddressTypeFilter
        self.show_used = AddressUsageStateFilter.ALL  # type: AddressUsageStateFilter
        self.change_button = QComboBox(self)
        self.change_button.currentIndexChanged.connect(self.toggle_change)
        for addr_type in AddressTypeFilter.__members__.values(
        ):  # type: AddressTypeFilter
            self.change_button.addItem(addr_type.ui_text())
        self.used_button = QComboBox(self)
        self.used_button.currentIndexChanged.connect(self.toggle_used)
        for addr_usage_state in AddressUsageStateFilter.__members__.values(
        ):  # type: AddressUsageStateFilter
            self.used_button.addItem(addr_usage_state.ui_text())
        self.std_model = QStandardItemModel(self)
        self.proxy = MySortModel(self, sort_role=self.ROLE_SORT_ORDER)
        self.proxy.setSourceModel(self.std_model)
        self.setModel(self.proxy)
        self.update()
        self.sortByColumn(self.Columns.TYPE, Qt.AscendingOrder)

    def get_toolbar_buttons(self):
        return QLabel(_("Filter:")), self.change_button, self.used_button

    def on_hide_toolbar(self):
        self.show_change = AddressTypeFilter.ALL  # type: AddressTypeFilter
        self.show_used = AddressUsageStateFilter.ALL  # type: AddressUsageStateFilter
        self.update()

    def save_toolbar_state(self, state, config):
        config.set_key('show_toolbar_addresses', state)

    def refresh_headers(self):
        fx = self.parent.fx
        if fx and fx.get_fiat_address_config():
            ccy = fx.get_currency()
        else:
            ccy = _('Fiat')
        headers = {
            self.Columns.TYPE: _('Type'),
            self.Columns.ADDRESS: _('Address'),
            self.Columns.LABEL: _('Label'),
            self.Columns.COIN_BALANCE: _('Balance'),
            self.Columns.FIAT_BALANCE: ccy + ' ' + _('Balance'),
            self.Columns.NUM_TXS: _('Tx'),
        }
        self.update_headers(headers)

    def toggle_change(self, state: int):
        if state == self.show_change:
            return
        self.show_change = AddressTypeFilter(state)
        self.update()

    def toggle_used(self, state: int):
        if state == self.show_used:
            return
        self.show_used = AddressUsageStateFilter(state)
        self.update()

    @profiler
    def update(self):
        if self.maybe_defer_update():
            return
        current_address = self.current_item_user_role(col=self.Columns.LABEL)
        if self.show_change == AddressTypeFilter.RECEIVING:
            addr_list = self.wallet.get_receiving_addresses()
        elif self.show_change == AddressTypeFilter.CHANGE:
            addr_list = self.wallet.get_change_addresses()
        else:
            addr_list = self.wallet.get_addresses()
        self.proxy.setDynamicSortFilter(
            False)  # temp. disable re-sorting after every change
        self.std_model.clear()
        self.refresh_headers()
        fx = self.parent.fx
        set_address = None
        addresses_beyond_gap_limit = self.wallet.get_all_known_addresses_beyond_gap_limit(
        )
        for address in addr_list:
            num = self.wallet.get_address_history_len(address)
            label = self.wallet.labels.get(address, '')
            c, u, x = self.wallet.get_addr_balance(address)
            balance = c + u + x
            is_used_and_empty = self.wallet.is_used(address) and balance == 0
            if self.show_used == AddressUsageStateFilter.UNUSED and (
                    balance or is_used_and_empty):
                continue
            if self.show_used == AddressUsageStateFilter.FUNDED and balance == 0:
                continue
            if self.show_used == AddressUsageStateFilter.USED_AND_EMPTY and not is_used_and_empty:
                continue
            balance_text = self.parent.format_amount(balance, whitespaces=True)
            # create item
            if fx and fx.get_fiat_address_config():
                rate = fx.exchange_rate()
                fiat_balance = fx.value_str(balance, rate)
            else:
                fiat_balance = ''
            labels = [
                '', address, label, balance_text, fiat_balance,
                "%d" % num
            ]
            address_item = [QStandardItem(e) for e in labels]
            # align text and set fonts
            for i, item in enumerate(address_item):
                item.setTextAlignment(Qt.AlignVCenter)
                if i not in (self.Columns.TYPE, self.Columns.LABEL):
                    item.setFont(QFont(MONOSPACE_FONT))
            self.set_editability(address_item)
            address_item[self.Columns.FIAT_BALANCE].setTextAlignment(
                Qt.AlignRight | Qt.AlignVCenter)
            # setup column 0
            if self.wallet.is_change(address):
                address_item[self.Columns.TYPE].setText(_('change'))
                address_item[self.Columns.TYPE].setBackground(
                    ColorScheme.YELLOW.as_color(True))
            else:
                address_item[self.Columns.TYPE].setText(_('receiving'))
                address_item[self.Columns.TYPE].setBackground(
                    ColorScheme.GREEN.as_color(True))
            address_item[self.Columns.LABEL].setData(address, Qt.UserRole)
            address_path = self.wallet.get_address_index(address)
            address_item[self.Columns.TYPE].setData(address_path,
                                                    self.ROLE_SORT_ORDER)
            address_path_str = self.wallet.get_address_path_str(address)
            if address_path_str is not None:
                address_item[self.Columns.TYPE].setToolTip(address_path_str)
            address_item[self.Columns.FIAT_BALANCE].setData(
                balance, self.ROLE_SORT_ORDER)
            # setup column 1
            if self.wallet.is_frozen_address(address):
                address_item[self.Columns.ADDRESS].setBackground(
                    ColorScheme.BLUE.as_color(True))
            if address in addresses_beyond_gap_limit:
                address_item[self.Columns.ADDRESS].setBackground(
                    ColorScheme.RED.as_color(True))
            # add item
            count = self.std_model.rowCount()
            self.std_model.insertRow(count, address_item)
            address_idx = self.std_model.index(count, self.Columns.LABEL)
            if address == current_address:
                set_address = QPersistentModelIndex(address_idx)
        self.set_current_idx(set_address)
        # show/hide columns
        if fx and fx.get_fiat_address_config():
            self.showColumn(self.Columns.FIAT_BALANCE)
        else:
            self.hideColumn(self.Columns.FIAT_BALANCE)
        self.filter()
        self.proxy.setDynamicSortFilter(True)

    def create_menu(self, position):
        from electrum_mona.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selected_in_column(self.Columns.ADDRESS)
        if not selected:
            return
        multi_select = len(selected) > 1
        addrs = [self.item_from_index(item).text() for item in selected]
        menu = QMenu()
        if not multi_select:
            idx = self.indexAt(position)
            if not idx.isValid():
                return
            item = self.item_from_index(idx)
            if not item:
                return
            addr = addrs[0]
            addr_column_title = self.std_model.horizontalHeaderItem(
                self.Columns.LABEL).text()
            addr_idx = idx.sibling(idx.row(), self.Columns.LABEL)
            self.add_copy_menu(menu, idx)
            menu.addAction(_('Details'),
                           lambda: self.parent.show_address(addr))
            persistent = QPersistentModelIndex(addr_idx)
            menu.addAction(_("Edit {}").format(addr_column_title),
                           lambda p=persistent: self.edit(QModelIndex(p)))
            #menu.addAction(_("Request payment"), lambda: self.parent.receive_at(addr))
            if self.wallet.can_export():
                menu.addAction(_("Private key"),
                               lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message"),
                               lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message"),
                               lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"),
                               lambda: self.parent.remove_address(addr))
            addr_URL = block_explorer_URL(self.config, 'addr', addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"),
                               lambda: webopen(addr_URL))

            if not self.wallet.is_frozen_address(addr):
                menu.addAction(
                    _("Freeze"), lambda: self.parent.
                    set_frozen_state_of_addresses([addr], True))
            else:
                menu.addAction(
                    _("Unfreeze"), lambda: self.parent.
                    set_frozen_state_of_addresses([addr], False))

        coins = self.wallet.get_spendable_coins(addrs)
        if coins:
            menu.addAction(_("Spend from"),
                           lambda: self.parent.utxo_list.set_spend_list(coins))

        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))

    def place_text_on_clipboard(self, text: str, *, title: str = None) -> None:
        if is_address(text):
            try:
                self.wallet.check_address_for_corruption(text)
            except InternalAddressCorruption as e:
                self.parent.show_error(str(e))
                raise
        super().place_text_on_clipboard(text, title=title)
        spinBox.interpretText()
        value = spinBox.value()

        model.setData(index, value, Qt.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)


if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)

    model = QStandardItemModel(4, 2)
    tableView = QTableView()
    tableView.setModel(model)

    delegate = SpinBoxDelegate()
    tableView.setItemDelegate(delegate)

    for row in range(4):
        for column in range(2):
            index = model.index(row, column, QModelIndex())
            model.setData(index, (row + 1) * (column + 1))

    tableView.setWindowTitle("Spin Box Delegate")
    tableView.show()
    sys.exit(app.exec_())
Exemple #11
0
class YoutubeDLGui(QMainWindow):
    def __init__(self):
        super(YoutubeDLGui, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        Center(self)
        self.download_model = QStandardItemModel(0, 5, self)
        self.download_model.setHeaderData(0, QtCore.Qt.Horizontal, 'Name')
        self.download_model.setHeaderData(1, QtCore.Qt.Horizontal, 'Progress')
        self.download_model.setHeaderData(2, QtCore.Qt.Horizontal, 'Size')
        self.download_model.setHeaderData(3, QtCore.Qt.Horizontal, 'ETA')
        self.download_model.setHeaderData(4, QtCore.Qt.Horizontal, 'Speed')
        self.ui.downloadView.setModel(self.download_model)
        self.pending_model = QStandardItemModel(0, 2, self)
        self.pending_model.setHeaderData(0, QtCore.Qt.Horizontal, 'Name')
        self.pending_model.setHeaderData(1, QtCore.Qt.Horizontal, 'Quality')
        self.ui.pendingView.setModel(self.pending_model)
        self.ui.pendingView.setItemDelegate(CustomToolTipDelegate(self.ui.pendingView))
        self.init_status_bar()
        self.parsing_worker = WorkerBuilder.build(bool)
        self.pending_list = []

    def init_status_bar(self):
        self.pending_progressbar = QProgressBar()
        self.pending_progressbar.setFixedHeight(20)
        self.pending_progressbar.setFixedWidth(150)
        self.pending_progressbar.setMaximum(0)
        self.pending_progressbar.setMinimum(0)
        self.pending_label = QLabel("")
        self.pending_label.setAlignment(QtCore.Qt.AlignLeading)
        self.pending_label.setFixedWidth(220)
        font = self.pending_label.font()
        font.setPointSize(10)
        self.pending_label.setFont(font)
        self.pending_label.setStyleSheet("padding-left: 5px")
        self.pending_progressbar.setVisible(False)

        self.statusBar().addPermanentWidget(self.pending_progressbar)
        self.statusBar().addWidget(self.pending_label)

    @pyqtSlot()
    def on_addBtn_clicked(self):
        url = CustomInputDialog.get_text("Url", "Enter Url")

        if not url[1]:
            return

        if not validators.url(url[0]):
            QMessageBox.information(self, "Invalid Url", "Please enter a valid url")
            self.on_addBtn_clicked()

        ydl_logger = YDLLogger()
        ydl_logger.debug_message.connect(self.on_debug_message_emitted)
        ydl_opt = {
            'logger': ydl_logger
        }
        self.ui.addBtn.setEnabled(False)
        self.parser = InfoParser(url[0], ydl_opt)
        self.parsing_worker.set_up(self.parser.generate_info, self.on_parsing_done)
        self.parsing_worker.start()
        self.pending_progressbar.setVisible(True)

    @pyqtSlot(int)
    def on_combobox_currentIndexChanged(self, index):
        list_index = self.ui.pendingView.currentIndex().row()
        self.pending_list[list_index].current_format = self.pending_list[list_index].format_info[index]

    @pyqtSlot(str)
    def on_debug_message_emitted(self, msg):
        self.pending_label.setText(msg)

    def add_to_pending(self, ydl_obj):
        if ydl_obj in self.pending_list:
            return

        index = len(self.pending_list)
        self.pending_list.append(ydl_obj)

        self.pending_model.insertRow(index)
        self.pending_model.setData(self.pending_model.index(index, 0), ydl_obj.title)
        model_index = self.pending_model.index(index, 0)
        self.ui.pendingView.setCurrentIndex(model_index)
        self.ui.pendingView.selectionModel().select(model_index, QItemSelectionModel.ClearAndSelect)

        combobox = QComboBox()
        combobox.currentIndexChanged[int].connect(self.on_combobox_currentIndexChanged)
        for ydl_format in ydl_obj.info:
            format_text = "%s, %s, %s" % (ydl_format['extension'], ydl_format['resolution'], ydl_format['filesize'])
            combobox.addItem(format_text)
        self.ui.pendingView.setIndexWidget(self.pending_model.index(index, 1), combobox)

        self.ui.tabWidget.setCurrentIndex(1)

    def on_parsing_done(self, success):
        self.pending_progressbar.setVisible(False)
        self.pending_label.setText("")
        self.ui.addBtn.setEnabled(True)
        if success:
            self.add_to_pending(self.parser.ydl_object)
        else:
            self.parsing_worker.quit()
            self.ui.addBtn.setEnabled(True)
            QMessageBox.information(self, "Invalid Url", "Unable to parse url")
Exemple #12
0
class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.select_checkbox_num = 0
        self.all_widgets = []
        self.game_sub_menus = []
        self.face_sub_menus = []
        self.setupUi(self)
        self.updateMenu(self)
        self.retranslateUi(self)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(775, 532)

        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 775, 23))
        self.menubar.setObjectName("menubar")

        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")

        self.menu_team = QtWidgets.QMenu(self.menubar)  #参赛队组建菜单
        self.menu_team.setObjectName("menu_team")

        self.menu_face = QtWidgets.QMenu(self.menubar)  #对阵组建
        self.menu_face.setObjectName("menu_face")

        MainWindow.setMenuBar(self.menubar)

        mgr_player = QAction(QIcon(), '运动员管理', self)
        mgr_player.triggered.connect(
            functools.partial(self.edit_player, *self.get_player_parmas()))

        mgr_playground = QAction(QIcon(), '场地管理', self)
        mgr_playground.triggered.connect(
            functools.partial(self.edit_player, *self.get_playground_parmas()))

        mgr_game = QAction(QIcon(), '竞赛项目', self)
        mgr_game.triggered.connect(
            functools.partial(self.edit_player, *self.get_game_parmas()))

        mgr_team = QAction(QIcon(), '参赛团队', self)
        mgr_team.triggered.connect(self.edit_team)

        mgr_group = QAction(QIcon(), '分组管理', self)
        mgr_group.triggered.connect(self.edit_group)

        mgr_test = QAction(QIcon(), '我的测试', self)
        mgr_test.triggered.connect(self.test)

        # mgr_face = QAction(QIcon(),'对阵设定',self)
        # mgr_face.triggered.connect(self.edit_face)

        self.toolbar = self.addToolBar('Mytool')
        self.toolbar.addAction(mgr_player)
        self.toolbar.addAction(mgr_playground)
        self.toolbar.addAction(mgr_game)
        self.toolbar.addAction(mgr_team)
        self.toolbar.addAction(mgr_group)
        self.toolbar.addAction(mgr_test)
        # self.toolbar.addAction(mgr_face)

        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.action_init = QtWidgets.QAction(MainWindow)
        self.action_init.setObjectName("action_init")

        self.action_import_data = QtWidgets.QAction(MainWindow)
        self.action_import_data.setObjectName("action_import_data")

        self.action_gamemgr = QtWidgets.QAction(MainWindow)
        self.action_gamemgr.setObjectName("action_gamemgr")

        self.menu.addAction(self.action_init)
        self.menu.addAction(self.action_import_data)
        self.menu.addSeparator()

        self.menubar.addAction(self.menu.menuAction())
        self.menubar.addAction(self.menu_team.menuAction())
        self.menubar.addAction(self.menu_face.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.action_init.triggered.connect(self.clear_data_firm)
        self.action_import_data.triggered.connect(self.get_data_file)

        self.add_first_ui()

        # if has_data():
        #     self.add_team_ui()
        # time.sleep(2)
        # self.centralwidget.hide()

    # def pr(self):
    #     print('prrrrr')

    def updateMenu(self, MainWindow):
        """添加或更新为每个竞赛项目组队的‘参赛队组建’菜单"""
        self.games = get_games()
        # 清除‘参赛队组建’原子菜单
        for game_sub_menu in self.game_sub_menus:
            self.menu_team.removeAction(game_sub_menu)

        for game in self.games:
            self.game_sub_menus.append(QtWidgets.QAction(MainWindow))

        for game_sub_menu, game in zip(self.game_sub_menus, self.games):
            game_sub_menu.setObjectName(game.name)
            game_sub_menu.triggered.connect(
                functools.partial(self.select_player, game.id, game.name,
                                  game.team_num, game.sex))
            game_sub_menu.setText(
                QtCore.QCoreApplication.translate("MainWindow",
                                                  "&{}".format(game.name)))

        for game_sub_menu in self.game_sub_menus:
            self.menu_team.addAction(game_sub_menu)
        """添加或更新为每个竞赛项目组队的‘对阵组建’菜单"""
        for face_sub_menu in self.face_sub_menus:
            self.menu_face.removeAction(face_sub_menu)

        for game in self.games:
            self.face_sub_menus.append(QtWidgets.QAction(MainWindow))

        for game_sub_menu, game in zip(self.face_sub_menus, self.games):
            game_sub_menu.setObjectName(game.name + '_')
            game_sub_menu.triggered.connect(
                functools.partial(self.new_face, game.id))
            game_sub_menu.setText(
                QtCore.QCoreApplication.translate("MainWindow",
                                                  "&{}".format(game.name)))

        for game_sub_menu in self.face_sub_menus:
            self.menu_face.addAction(game_sub_menu)

    def add_first_ui(self, info="Welcome!"):
        self.takeCentralWidget()
        self.main_frame = QScrollArea(self)
        self.main_frame.setStyleSheet(
            'QWidget{background-color:rgb(255,255,255)}')
        self.wel = QLabel(info)

        boxlayout = QHBoxLayout()
        boxlayout.addStretch()
        boxlayout.addWidget(self.wel)
        boxlayout.addStretch()

        self.main_frame.setLayout(boxlayout)
        self.setCentralWidget(self.main_frame)

    # def add_team_ui(self):
    #     self.centralwidget = QWidget()
    #     self.form_layout = QHBoxLayout(self.centralwidget)

    #     self.left_layout = MyQVBoxLayout()
    #     self.right_layout = QVBoxLayout()

    #     # qbtn = QPushButton('1')
    #     # qbtn.resize(qbtn.minimumSize())
    #     self.left_widgts = self.get_left_widgts()
    #     # self.left_layout.addWidget(qbtn)
    #     # self.left_layout.addWidget(QLabel('def'))
    #     for widgt in self.left_widgts:
    #         self.left_layout.addWidget(widgt)
    #     self.left_layout.addStretch()
    #     # self.right_layout.addWidget(QLabel('aaaa'),0,0)
    #     # self.right_layout.addWidget(QLabel('bbbb'),1,0)
    #     self.right_widgts = self.get_right_widgets()
    #     for widgt in self.right_widgts:
    #         self.right_layout.addWidget(widgt)
    #     self.right_layout.addStretch()
    #     self.form_layout.addLayout(self.left_layout)
    #     self.form_layout.addLayout(self.right_layout)

    #     self.setCentralWidget(self.centralwidget)

    #     qbtn.clicked.connect(self.test)

    # def test(self):
    #     centralwidget = QWidget()
    #     test_layout = QHBoxLayout(centralwidget)
    #     test_layout.addWidget(QLabel('kkkkkkkkkkkkkkkkkkk'))
    #     # self.removeWidget(self.centralwidget)
    #     self.takeCentralWidget()
    #     self.setCentralWidget(centralwidget)
    #     # self.show()
    #     # self.update()
    #     # self.repaint()

    # def test_tool(self):
    #     print('abccc')
    #     self.wel.setText('akkkkkkkkkkkk!')
    #     self.takeCentralWidget()
    #     self.setCentralWidget(QLabel('kkkdkddaaaaaaaaaaaaaa'))

#         main_form = QFormLayout()
#         left_widgt = QWidget(None)
#         left_widgt_layout = QVBoxLayout()
#         left_widgt.setLayout(left_widgt_layout)
#         for i in range(5):
#             left_widgt_layout.addWidget(QLabel('标签%i' % i))

#         for w in self.get_left_widgts():
#             left_widgt_layout.addWidget(w)

#         scroll_area = QScrollArea()
#         right_widgt = QWidget(None)
#         self.right_widgt_layout = QVBoxLayout()
#         right_widgt.setLayout(self.right_widgt_layout)
#         self.right_widgt_layout.addWidget(QLabel('标签%i' % 5))
#         self.right_widgt_layout.addWidget(QLabel('标签%i' % 7))
#         scroll_area.setWidget(right_widgt)

#         main_form.addRow(left_widgt,scroll_area)

#         main_widgt = QWidget(None)
#         main_widgt.setLayout(main_form)
#         self.setCentralWidget(main_widgt)

# def get_left_widgts(self):
#     widgts = []
#     self.game_data = get_games()
#     mylbl = QLabel('运动项目:')
#     mylbl.setMaximumHeight(20)
#     widgts.append(mylbl)
#     self.game_combo = QComboBox(None)
#     self.game_combo.setMaximumWidth(80)
#     self.game_combo.setMaximumHeight(20)
#     for item in self.game_data.keys():
#         self.game_combo.addItem(item)
#     widgts.append(self.game_combo)
#     self.game_combo.setCurrentIndex(-1)
#     self.game_combo.activated[str].connect(self.set_cur_game)
#     return widgts

# def set_cur_game(self,game):
#     self.game = game
#     print(game,self.game_data[game])
#     if self.game_data[game] == 1:
#         self.show_players(game)

# def get_right_widgets(self):
#     players = get_players()
#     widgts = []

#     for p in players:
#         data = [p.name,p.idcode,p.sex,p.age,p.work_place,p.tel]
#         data = ['' if d is None else d for d in data]
#         info = '{: <8} {: <8} {: <2} {: <2} {: <10} {: <12}'.format(*data)
#         widgts.append(QLabel(info))
#     return widgts

# def show_players(self,game):
#     self.test()

#     game_sex = get_games_sex()
#     sex = game_sex[game]
#     self.players = get_players(sex)
#     self.p_checkboxes = [QCheckBox(' '.join((p.name,p.idcode))) for p in self.players]
#     for w in self.right_widgts:
#         w.hide()
#     for cb in self.p_checkboxes:
#         cb.toggle()
#         print('abc')
#         self.right_layout.addWidget(cb)
#     self.right_layout.addStretch()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "易用竞赛管理系统"))
        self.menu.setTitle(_translate("MainWindow", "&管理数据"))
        self.action_init.setText(_translate("MainWindow", "&清理数据"))
        self.action_import_data.setText(_translate("MainWindow", "&导入数据"))

        self.menu_team.setTitle(_translate("MainWindow", "&参赛队组建"))

        self.menu_face.setTitle(_translate("MainWindow", "&对阵组建"))

    def get_data_file(self):
        fname = QFileDialog.getOpenFileName(self, '打开文件', '.\\')
        if fname[0]:
            info = load_data(fname[0])
            if info:
                QMessageBox.information(self, "数据错误,请修改后重新导入!", info)
            else:
                QMessageBox.information(self, "提示:", '数据导入成功!')
                self.add_first_ui('数据已导入!')
                # self.add_team_ui()
                self.updateMenu(self)

    def clear_data_firm(self):
        reply = QMessageBox.question(self, '确认', '确定删除数据?',
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        self.takeCentralWidget()
        if reply == QMessageBox.Yes:
            clear_data()
            self.add_first_ui('数据已全部清空!')

    def get_player_parmas(self):
        head_lst = ['索引号', '姓名', '身份证号', '性别', '年龄', '工作单位', '电话']
        keys = ['id', 'name', 'idcode', 'sex', 'age', 'work_place', 'tel']
        return get_players, keys, head_lst, Player

    def get_playground_parmas(self):
        head_lst = ['索引号', '场地名', '使用状态', '备注']
        keys = ['id', 'name', 'using', 'memo']
        return get_playgrounds, keys, head_lst, PlayGround

    def get_game_parmas(self):
        head_lst = ['索引号', '竞赛项目', '队员人数', '队员性别', '备注']
        keys = ['id', 'name', 'team_num', 'sex', 'memo']
        return get_games, keys, head_lst, Games

    def edit_player(self, getfunc, keys, head_lst, obj):
        model_objs = getfunc()
        datas = []
        for model_obj in model_objs:
            # data = [p.id,p.name,p.idcode,p.sex,p.age,p.work_place,p.tel]
            data = [getattr(model_obj, key) for key in keys]
            data = ['' if d is None else d for d in data]
            datas.append(data)
        # head_lst = ['索引号','姓名','身份证号','性别','年龄','工作单位','电话']
        if datas:
            self.takeCentralWidget()
            main_frame = QScrollArea(self)
            main_frame.setStyleSheet(
                'QWidget{background-color:rgb(255,255,255)}')

            self.player_tabview = QTableView()
            r, c = len(datas), len(datas[0])
            self.player_model = QStandardItemModel(r, c)
            self.player_model.setHorizontalHeaderLabels(head_lst)
            for r, rdata in enumerate(datas):
                for c, cell in enumerate(rdata):
                    it = QStandardItem(str(cell))
                    if c == 0:
                        it.setEditable(False)
                    self.player_model.setItem(r, c, it)
            # keys = ['id','name','idcode','sex','age','work_place','tel']
            edit_cell = functools.partial(self.edit_cell, obj, keys)
            self.player_model.itemChanged.connect(edit_cell)

            self.player_tabview.setModel(self.player_model)

            boxlayout = QVBoxLayout()
            # boxlayout.addStretch(1)
            boxlayout.addWidget(self.player_tabview, 18)
            # boxlayout.addStretch(1)

            del_btn = QPushButton('删除')
            del_btn.clicked.connect(functools.partial(self.del_row, obj))
            boxlayout.addWidget(del_btn)

            main_frame.setLayout(boxlayout)
            self.setCentralWidget(main_frame)

    def edit_cell(self, obj, keys):
        r = self.player_tabview.currentIndex().row()
        c = self.player_tabview.currentIndex().column()
        curr_data = self.player_tabview.currentIndex().data()
        item = self.player_model.index(r, 0)
        param = dict()
        param[keys[c]] = curr_data
        save_cell(obj, int(item.data()), param)
        if obj == Games and 'name' in param:
            self.updateMenu(self)

    def del_row(self, obj):
        reply = QMessageBox.question(self, '确认', '确定删除数据?',
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            r = self.player_tabview.currentIndex().row()
            item = self.player_model.index(r, 0)
            # print(int(item.data()))
            del_rowdb(obj, int(item.data()))
            self.player_model.removeRow(r)
            if obj == Games:
                self.updateMenu(self)

    def edit_team(self):
        datas = get_team_datas()
        head_lst = ['索引号', '队名', '项目', '分组']
        if datas:
            self.takeCentralWidget()
            main_frame = QScrollArea(self)
            main_frame.setStyleSheet(
                'QWidget{background-color:rgb(255,255,255)}')

            self.player_tabview = QTableView()
            r, c = len(datas), len(datas[0])
            self.player_model = QStandardItemModel(r, c)
            self.player_model.setHorizontalHeaderLabels(head_lst)
            for r, rdata in enumerate(datas):
                for c, cell in enumerate(rdata):
                    it = QStandardItem(str(cell))
                    if c == 0:
                        it.setEditable(False)
                    self.player_model.setItem(r, c, it)
            # keys = ['id','name','idcode','sex','age','work_place','tel']
            # edit_cell = functools.partial(self.edit_cell,obj,keys)
            # self.player_model.itemChanged.connect(edit_cell)

            self.player_tabview.setModel(self.player_model)

            boxlayout = QVBoxLayout()
            # boxlayout.addStretch(1)
            boxlayout.addWidget(self.player_tabview, 18)
            # boxlayout.addStretch(1)

            del_btn = QPushButton('删除')
            del_btn.clicked.connect(self.del_team)
            boxlayout.addWidget(del_btn)

            main_frame.setLayout(boxlayout)
            self.setCentralWidget(main_frame)

    def del_team(self):
        # v = MyDialog()
        # if v.exec_():
        #     name,game = v.get_data()
        #     print(name,game)
        reply = QMessageBox.question(self, '确认', '确定删除数据?',
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            r = self.player_tabview.currentIndex().row()
            item = self.player_model.index(r, 0)
            # print(int(item.data()))
            del_rowdb(Team, int(item.data()))
            self.player_model.removeRow(r)

    def select_player(self, gid, gname, gteam_num, gsex):
        # 新建团队UI
        players = get_players(gsex)
        head_lst = ['索引号', '姓名', '身份证号', '性别', '年龄', '工作单位', '电话']
        keys = ['id', 'name', 'idcode', 'sex', 'age', 'work_place', 'tel']
        datas = []
        for player in players:
            data = [getattr(player, key) for key in keys]
            data = ['' if d is None else d for d in data]
            datas.append(data)
        if datas:
            self.takeCentralWidget()
            main_frame = QScrollArea(self)
            main_frame.setStyleSheet(
                'QWidget{background-color:rgb(255,255,255)}')

            self.player_tabview = QTableView()
            r, c = len(datas), len(datas[0])
            self.player_model = QStandardItemModel(r, c)

            print(self.player_tabview.itemDelegate())

            self.player_model.setHorizontalHeaderLabels(head_lst)
            for r, rdata in enumerate(datas):
                for c, cell in enumerate(rdata):
                    it = QStandardItem(str(cell))
                    if c == 0:
                        it.setEditable(False)
                    self.player_model.setItem(r, c, it)
            self.player_tabview.setModel(self.player_model)

            boxlayout = QVBoxLayout()
            # boxlayout.addStretch(1)
            boxlayout.addWidget(self.player_tabview, 18)
            # boxlayout.addStretch(1)

            new_btn = QPushButton('新建团队({})'.format(gname))
            new_btn.clicked.connect(
                functools.partial(self.add_team, gid, gteam_num, gsex))
            boxlayout.addWidget(new_btn)

            main_frame.setLayout(boxlayout)
            self.setCentralWidget(main_frame)

    def add_team(self, gid, gteam_num, gsex):
        # 新建团队方法
        rows = set()
        pids = []
        for selected_model_index in self.player_tabview.selectedIndexes():
            rows.add(selected_model_index.row())
        for r in rows:
            item = self.player_model.index(r, 0)
            pids.append(item.data())
        if gteam_num == 1:
            info = new_team(gid, pids, flag=1)
            if info:
                QMessageBox.warning(self, '完成', info, QMessageBox.Ok)
            else:
                QMessageBox.information(self, '完成', '成功建立!', QMessageBox.Ok)
        if gteam_num > 1:
            if len(rows) == gteam_num:
                info = new_team(gid, pids)
                if info:
                    QMessageBox.warning(self, '完成', info, QMessageBox.Ok)
                else:
                    QMessageBox.information(self, '完成', '成功建立!',
                                            QMessageBox.Ok)
            else:
                QMessageBox.warning(self, '错误',
                                    '请选中指定的运动员数:{}'.format(gteam_num),
                                    QMessageBox.Ok)
        self.player_tabview.clearSelection()

    def test(self):
        from .modeltt import TObjModel, MyDelegate
        md = MyDelegate()
        self.takeCentralWidget()
        main_frame = QScrollArea(self)
        main_frame.setStyleSheet('QWidget{background-color:rgb(255,255,255)}')

        self.player_tabview = QTableView()
        self.player_model = TObjModel()
        self.player_tabview.setModel(self.player_model)

        boxlayout = QVBoxLayout()
        # boxlayout.addStretch(1)
        boxlayout.addWidget(self.player_tabview, 18)
        self.player_tabview.setItemDelegateForColumn(2, md)
        self.player_tabview.hideColumn(0)
        main_frame.setLayout(boxlayout)
        self.setCentralWidget(main_frame)

    def edit_group(self):
        datas = get_group_datas()
        head_lst = ['索引号', '组名', '项目', '所含队名', 'gameid']
        self.takeCentralWidget()
        main_frame = QScrollArea(self)
        main_frame.setStyleSheet('QWidget{background-color:rgb(255,255,255)}')

        self.player_tabview = QTableView()
        self.player_model = QStandardItemModel()
        self.player_model.setHorizontalHeaderLabels(head_lst)
        if datas:
            r, c = len(datas), len(datas[0])
            # self.player_model = QStandardItemModel(r,c)
            self.player_model.setHorizontalHeaderLabels(head_lst)
            for r, rdata in enumerate(datas):
                for c, cell in enumerate(rdata):
                    it = QStandardItem(str(cell))
                    # if c == 0:
                    it.setEditable(False)
                    self.player_model.setItem(r, c, it)
        # keys = ['id','name','idcode','sex','age','work_place','tel']
        # edit_cell = functools.partial(self.edit_cell,obj,keys)
        # self.player_model.itemChanged.connect(edit_cell)

        self.player_tabview.setModel(self.player_model)

        boxlayout = QVBoxLayout()
        # boxlayout.addStretch(1)
        boxlayout.addWidget(self.player_tabview, 18)
        # boxlayout.addStretch(1)
        self.player_tabview.hideColumn(4)

        add_btn = QPushButton('添加分组')
        add_btn.clicked.connect(self.add_group)
        boxlayout.addWidget(add_btn)

        del_btn = QPushButton('删除分组')
        del_btn.clicked.connect(functools.partial(self.del_row, Group))
        boxlayout.addWidget(del_btn)

        add_team_btn = QPushButton('分配参赛团队')
        add_team_btn.clicked.connect(self.add_team2group)
        boxlayout.addWidget(add_team_btn)

        main_frame.setLayout(boxlayout)
        self.setCentralWidget(main_frame)

    def add_group(self):
        v = MyDialog()
        if v.exec_():
            name, game = v.get_data()
            if name and game:
                info = add_groupdb(name, int(game))
                if info:
                    QMessageBox.warning(self, '错误', info, QMessageBox.Ok)
                else:
                    QMessageBox.information(self, '完成', '成功建立!',
                                            QMessageBox.Ok)
                    self.edit_group()

    def add_team2group(self):
        rows = set()

        for selected_model_index in self.player_tabview.selectedIndexes():
            rows.add(selected_model_index.row())
        if len(rows) != 1:
            QMessageBox.warning(self, '错误', '请仅选择其中一个小组', QMessageBox.Ok)
            return
        row = rows.pop()
        groupid = self.player_model.index(row, 0).data()
        gameid = self.player_model.index(row, 4).data()

        print(groupid, gameid)
        if get_team_datas(gameid):
            v = GroupDialog(gameid, "添加团队到小组", get_team_datas)
            if v.exec_():
                tids = v.get_data()
                print(tids)
                if tids:
                    add_team2group_db(groupid, tids)
                    QMessageBox.information(self, '提示', '操作完成!',
                                            QMessageBox.Ok)
        else:
            QMessageBox.information(self, '提示', '无参赛团队可以分组!', QMessageBox.Ok)

    def get_grp_combo(self, gid):
        groups = get_group_for_game(gid)
        cur_index = -1
        grp_combo = QComboBox()
        for index, (ggid, gname, ggname) in enumerate(groups):
            grp_combo.addItem('-'.join((ggname, gname)), ggid)

        grp_combo.setCurrentIndex(cur_index)

        grp_combo.currentIndexChanged.connect(
            functools.partial(self.disp_face, gid))
        grp_combo.setToolTip('请选择一个分组,并为其建立对阵。')

        return grp_combo

    def new_face(self, gid):
        # print(gid)
        self.takeCentralWidget()
        main_frame = QScrollArea(self)
        main_frame.setStyleSheet('QWidget{background-color:rgb(255,255,255)}')

        boxlayout = QVBoxLayout()

        self.grp_combo = self.get_grp_combo(gid)

        boxlayout.addWidget(self.grp_combo)
        # boxlayout.addStretch(1)

        self.face_view = QTableView()
        self.face_model = QStandardItemModel()
        self.face_model.setHorizontalHeaderLabels(['id', '队A', '队B'])
        self.face_view.setModel(self.face_model)

        boxlayout.addWidget(self.face_view)

        add_btn = QPushButton('添加对阵')
        add_btn.clicked.connect(functools.partial(self.add_face, gid))
        boxlayout.addWidget(add_btn)

        main_frame.setLayout(boxlayout)
        self.setCentralWidget(main_frame)

    def disp_face(self, gid):
        # print(self.grp_combo.currentIndex(),self.grp_combo.currentText())
        self.ggid = int(self.grp_combo.itemData(self.grp_combo.currentIndex()))
        if self.ggid >= 1:

            self.face_model.beginResetModel()
            self.face_model.clear()
            self.face_model.setHorizontalHeaderLabels(['id', '队A', '队B'])
            faces = get_faces(gid, self.ggid)
            for r, rd in enumerate(faces):
                for c, cd in enumerate(rd):
                    item = QStandardItem(str(cd))
                    item.setEditable(False)
                    self.face_model.setItem(r, c, item)
            self.face_model.endResetModel()

    def add_face(self, gid):

        v = GroupDialog(self.ggid, "添加对阵团队", get_teams_for_group)
        if v.exec_():
            tids = v.get_data()
            print(tids)
            tids = [int(tid) for tid in tids]
            if len(tids) != 2:
                QMessageBox.warning(self, '错误', '请仅选择对阵的双方小组', QMessageBox.Ok)
            else:
                tids.sort()
                if add_face2db(*tids):
                    self.disp_face(gid)
                    QMessageBox.information(self, '提示', '操作完成!',
                                            QMessageBox.Ok)
                else:
                    QMessageBox.warning(self, '错误', '对阵不能重复!', QMessageBox.Ok)
Exemple #13
0
class mainView(QtWidgets.QMainWindow, mainWin.Ui_MainWindow):
    """
    主窗口类
    """

    def __init__(self):
        super(mainView, self).__init__()
        self.setupUi(self)
        # 主要变量初始化
        self.isShow_flag = False
        self.account = "admin"
        self.password = "******"
        self.loadTimeStr = ""
        self.isAdmin = False
        self.curPage = 1
        self.totalPage = 1

        # 日志相关变量和类的初始化
        # self.log = logout.TimedRotatingFileLog("win_log",".\\log\\", "win.log",logging.DEBUG)
        self.log = logout.RotatingFileLog("win_log", ".\\log\\", "win.log", logging.DEBUG)
        self.msg_list = []
        self.msg_list2 = []
        self.DEBUG = 1
        self.INFO = 2
        self.WARNING = 3
        self.ERROR = 4
        self.CRITICAL = 5

        # 线程锁及线程信号量初始化
        self.mutex1 = QMutex()
        self.mutex2 = QMutex()
        self.signal = threading.Event()
        self.signal.clear()

        # 初始化数据库相关信息
        my_cof = config.config()
        # my_cof.cofig_update()
        my_cof.get_config()
        self.msg_level = my_cof.level["msg_level"]

        self.ip1 = my_cof.scanner["s1_ip"]  # "172.24.24.222"
        self.port1 = my_cof.scanner["s1_port"]  # 51236
        self.ip2 = my_cof.scanner["s2_ip"]  # "172.24.24.222"
        self.port2 = my_cof.scanner["s2_port"]  # 51236
        self.db = pymysql.Connect(my_cof.mysql["host"], my_cof.mysql["user"], my_cof.mysql["passwd"],
                                  my_cof.mysql["dbName"])
        self.cursor = self.db.cursor()

        # self.db = pymysql.Connect(mysql["host"], mysql["user"], mysql["passwd"], mysql["dbName"])
        # self.cursor = self.db.cursor()

        # 系统时间显示相关类初始化
        self.updateTime = QTimer()
        self.updateTime.start(1000)
        self.updateTime.timeout.connect(self.updateTimeShow)

        # 自动刷新显示列表定时器初始化
        self.Refresh_timer = QTimer()
        self.Refresh_timer.timeout.connect(self.refreshSelf)

        # 扫码枪未连接提示
        self.scanner_statue_timer = QTimer()
        self.scanner_statue_timer.timeout.connect(self.scanner_statu_change)
        self.scanner_statue_flag = False

        # PLC未连接提示
        self.plc_statue_timer = QTimer()
        self.plc_statue_timer.timeout.connect(self.plc_statue_change)
        self.plc_statue_flag = False

        # 初始化状态栏及时间栏相关类及变量初始化
        # self.setWhatsThis("123456789")
        self.statuLable = QtWidgets.QLabel()
        # self.errLable = QtWidgets.QLabel()
        self.nowTimeLable = QtWidgets.QLabel()
        self.statuLable.setAlignment(Qt.AlignLeft)
        # self.errLable.setAlignment(Qt.AlignCenter)
        self.nowTimeLable.setAlignment(Qt.AlignRight)
        self.statusbar.addWidget(self.statuLable)
        # self.statusbar.addWidget(self.errLable)
        self.statusbar.addWidget(self.nowTimeLable)
        self.statusbar.setStyleSheet("QStatusBar::item{border: 0px}")
        self.statuLable.setText("就绪")
        # self.errLable.setStyleSheet("color:red;font:bold;font-size:12px")
        # self.errLable.setText("异常显示")
        nowtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        self.nowTimeLable.setText(str(nowtime))
        self.nowTimeLable.setStyleSheet("color:blue;font-size:12px")
        self.statuLable.setStyleSheet("color:red;font-size:12px")

        # 用户及登陆信息栏初始化
        self.textLable.setStyleSheet("color:blue;font:bold;font-size:14px")
        self.userLable.setStyleSheet("color:red;font:bold;font-size:14px")
        self.loadTimeLable2.setStyleSheet("color:red;font:bold;font-size:14px")

        # 设置设置信息为只读
        self.machineID.setReadOnly(True)
        self.plantID.setReadOnly(True)
        self.processNo.setReadOnly(True)
        self.localityNo.setReadOnly(True)
        self.type.setReadOnly(True)
        self.loadTime.setReadOnly(True)
        self.classBox.setEnabled(False)

        # 初始化页码显示控件
        self.curPageNoEdit.setMaximumSize(QSize(40, 20))
        self.curPageNoEdit.setStyleSheet("color:blue;font:bold;font-size:14px")
        validator = QRegExpValidator(QRegExp("\d+"))
        self.curPageNoEdit.setValidator(validator)  # 设置只能输入数字
        self.curPageNoEdit.setText(str(self.curPage))
        self.curPageNoEdit.setAlignment(Qt.AlignCenter)
        self.totalPageLable.setStyleSheet("color:blue;font:bold;font-size:14px")

        # 设置PLC和扫码枪连接状态
        self.PlcConStatu.setText("PLC等待连接")
        self.ScanConStatu.setText("扫码枪等待连接")
        self.PlcConStatu.setStyleSheet("background:none;border:none;font:bold;font-size:12px;color:#FF8800")
        self.ScanConStatu.setStyleSheet("background:none;border:none;font:bold;font-size:12px;color:#FF8800")

        # 设置各类信号与槽
        self.prevPageBtn.clicked.connect(self.onClickedPrevPageBtn)
        self.nextPageBtn.clicked.connect(self.onClickedNextPageBtn)
        self.curPageNoEdit.returnPressed.connect(self.onPressedCurPageNoEdit)

        self.setBtn.clicked.connect(self.onClickedSetBtn)
        self.changePwdBtn.clicked.connect(self.onClickedChangePwdBtn)
        self.refreshBtn.clicked.connect(self.onClickedRefreshBtn)
        self.refreshSelfBtn.clicked.connect(self.onClickedRefreshSelfBtn)

        # 设置显示列表
        # self.showTable.setHorizontalHeaderLabels(["序号", "工字轮编号", "重量1", "称重时间1", "是否二次称重", "重量2", "称重时间2"])
        self.mode = QStandardItemModel()
        self.mode.setRowCount(15)
        self.mode.setColumnCount(7)
        for i in range(0, 15):
            for j in range(0, 7):
                self.mode.setItem(i, j, QStandardItem(""))
        self.mode.setHorizontalHeaderLabels(["序号", "工字轮编号", "重量1", "称重时间1", "是否二次称重", "重量2", "称重时间2"])
        self.showTable.setModel(self.mode)
        self.showTable.verticalHeader().setVisible(False)
        self.setTable()

        # 初始化登陆界面类
        self.loginView = loginView()
        self.loginView.loginBtn.clicked.connect(self.onClickedLoginBtn)
        self.loginView.loginBtn.pressed.connect(self.onClickedLoginBtn)
        self.loginView.account.returnPressed.connect(self.onClickedLoginBtn)
        self.loginView.password.returnPressed.connect(self.onClickedLoginBtn)

        # 初始化修改密码界面类
        self.changePwdView = changePwdView()
        self.changePwdView.changeBtn.clicked.connect(self.onClickedChangeBtn_c)
        self.changePwdView.changeBtn.pressed.connect(self.onClickedChangeBtn_c)
        self.changePwdView.oldPwd.returnPressed.connect(self.onClickedChangeBtn_c)
        self.changePwdView.newPwd1.returnPressed.connect(self.onClickedChangeBtn_c)
        self.changePwdView.newPwd2.returnPressed.connect(self.onClickedChangeBtn_c)

        self.logMsgView = logMsgView()

    def updateTimeShow(self):
        """
        系统时间显示程序
        :return:
        """
        nowtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        self.nowTimeLable.setText(str(nowtime))

    def loginShow(self):
        """
        登陆界面显示
        :return:
        """
        self.log_msg(flag=self.INFO, msg_str="启动登陆程序")
        self.loginView.show()
        self.loginView.account.setText(self.account)
        self.loginView.password.setText(self.password)

    def changePwdShow(self):
        """
        修改密码界面显示
        :return:
        """
        self.changePwdView.show()
        if self.isAdmin == True:
            self.changePwdView.setWindowTitle("系统设置")
        else:
            self.changePwdView.setWindowTitle("修改密码")
        self.changePwdView.oldPwd.setText("")
        self.changePwdView.newPwd1.setText("")
        self.changePwdView.newPwd2.setText("")

    def mainWinShow(self):
        """
        主界面显示
        :return:
        """
        self.userLable.setText(self.account)
        nowtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        self.loadTimeLable2.setText(str(nowtime))
        self.show()
        ret = self.getSpoolDate(pageNo=self.curPage)
        if ret == -1:
            return
        else:
            self.updateTable()
        ret = self.getTotalPage()
        if ret == -1:
            return
        else:
            self.totalPageLable.setText("/%d(共%d页)" % (self.totalPage, self.totalPage))
        ret = self.updateOnlineDate()
        if ret == -1:
            return
        self.getMachineSetDate()
        if self.isAdmin == True:
            self.changePwdBtn.setText("系统设置")
            QMessageBox.information(self, "提示", "管理员账户验证成功!         ", QMessageBox.Ok,
                                    QMessageBox.Ok)
            self.log_msg(flag=self.INFO, msg_str="管理员账户验证成功")
        self.T3.isStart = True
        self.T3.start()

    def verfiyAdmin(self):
        """
        确认登陆账号是否为管理员账号
        :return:
        """
        sqlStr = "SELECT * FROM adminuser WHERE uname = '%s'" % self.account
        try:
            self.cursor.execute(sqlStr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_str="数据异常请重新再试", msg_tuple=e)
            return -1
        result = self.cursor.fetchall()
        if len(result) > 0:
            self.isAdmin = True
        else:
            self.isAdmin = False
        return 0

    def onClickedLoginBtn(self):
        """
        确认登陆处理
        :return:
        """
        self.account = self.loginView.account.text()
        self.password = self.loginView.password.text()
        if self.account == "" or self.password == "":
            QMessageBox.warning(self, "提示", "用户名或密码不能为空!         ", QMessageBox.Ok,
                                QMessageBox.Ok)
            return
        sqlstr = "SELECT * FROM login WHERE uname = '%s'" % self.account
        try:
            self.cursor.execute(sqlstr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_tuple=e)
            return
        result = self.cursor.fetchall()
        if len(result) == 0:
            QMessageBox.warning(self, "提示", "该用户名不存在!         ", QMessageBox.Ok,
                                QMessageBox.Ok)
            return
        s1 = sha1(self.password.encode("utf-8"))
        pwd = s1.hexdigest()
        if result[0][2] == pwd:
            self.loadTimeStr = str(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
            self.loginView.close()
            ret = self.verfiyAdmin()
            if ret == -1:
                return
            else:
                self.mainWinShow()
                self.log_msg(flag=self.INFO, msg_str="%s账号登陆成功" % self.account)
        else:
            QMessageBox.warning(self, "提示", "密码错误!         ", QMessageBox.Ok,
                                QMessageBox.Ok)

    def onClickedPrevPageBtn(self):
        """
        点击上一页处理
        :return:
        """
        self.log_msg(flag=self.INFO, msg_str="查看上一页")
        if self.curPage == 1:
            return
        elif self.curPage > 1:
            ret = self.getSpoolDate(pageNo=self.curPage - 1)
            if ret == 0:
                self.updateTable()
                self.curPage -= 1
                self.curPageNoEdit.setText(str(self.curPage))
            else:
                return

    def onClickedNextPageBtn(self):
        """
        点击下一页处理
        :return:
        """
        self.log_msg(flag=self.INFO, msg_str="查看下一页")
        self.getTotalPage()
        self.totalPageLable.setText("/%d(共%d页)" % (self.totalPage, self.totalPage))
        if self.curPage == self.totalPage:
            return
        elif self.curPage < self.totalPage:
            ret = self.getSpoolDate(pageNo=self.curPage + 1)
            if ret == 0:
                self.updateTable()
                self.curPage += 1
                self.curPageNoEdit.setText(str(self.curPage))
            else:
                return

    def onPressedCurPageNoEdit(self):
        """
        enter键当前页码框处理
        :return:
        """
        ret = self.getTotalPage()
        if ret == -1:
            return
        else:
            self.totalPageLable.setText("/%d(共%d页)" % (self.totalPage, self.totalPage))
        pageNo = int(self.curPageNoEdit.text())
        if pageNo == self.curPage:
            self.onClickedRefreshBtn()
        if pageNo < 1:
            pageNo = 1
        elif pageNo <= self.totalPage:
            pageNo = pageNo
        else:
            pageNo = self.totalPage
        ret = self.getSpoolDate(pageNo=pageNo)
        if ret == 0:
            self.updateTable()
            self.curPage = pageNo
            self.curPageNoEdit.setText(str(self.curPage))
            self.log_msg(flag=self.INFO, msg_str="查看第 %d 页" % self.curPage)

    def onClickedSetBtn(self):
        """
        处理点击设置按钮程序
        :return:
        """
        btnStr = self.setBtn.text()
        if btnStr == "编   辑":
            self.log_msg(flag=self.INFO, msg_str="编辑......")
            if self.isAdmin == True:
                self.machineID.setReadOnly(False)
                self.plantID.setReadOnly(False)
                self.processNo.setReadOnly(False)
                self.localityNo.setReadOnly(False)
                self.type.setReadOnly(False)
                self.classBox.setEnabled(True)
            else:
                self.classBox.setEnabled(True)
            self.setBtn.setText("保   存")
            self.changSetBoxColor("red")

        if btnStr == "保   存":
            if self.isAdmin == True:
                self.machineID.setReadOnly(True)
                self.plantID.setReadOnly(True)
                self.processNo.setReadOnly(True)
                self.localityNo.setReadOnly(True)
                self.type.setReadOnly(True)
                self.classBox.setEnabled(False)
            else:
                self.classBox.setEnabled(False)
            ret = self.updataMachineSetDate()
            if ret == 0:
                self.log_msg(flag=self.INFO, msg_str="保存成功")
                self.setBtn.setText("编   辑")
                self.changSetBoxColor("black")

    def onClickedChangePwdBtn(self):
        """
        点击系统设置按钮处理程序
        :return:
        """
        self.changePwdShow()
        self.hide()
        self.changePwdView.exec()
        self.show()

    def onClickedRefreshBtn(self):
        """
        点击刷新按钮处理程序
        :return:
        """
        ret = self.getSpoolDate(pageNo=self.curPage)
        if ret == -1:
            return
        self.updateTable()
        ret = self.getTotalPage()
        if ret == -1:
            return
        else:
            self.totalPageLable.setText("/%d(共%d页)" % (self.totalPage, self.totalPage))
        self.setTable()
        self.log_msg(flag=self.INFO, msg_str="当前页刷新成功")

    def onClickedRefreshSelfBtn(self):
        """
        点击自动刷新按钮
        :return:
        """
        btnStr = self.refreshSelfBtn.text()
        if btnStr == "自动刷新":
            self.refreshSelfBtn.setText("停止刷新")
            self.Refresh_timer.start(1000)
            self.setBtn.setEnabled(False)
            self.refreshBtn.setEnabled(False)
            self.changePwdBtn.setEnabled(False)
            self.prevPageBtn.setEnabled(False)
            self.nextPageBtn.setEnabled(False)
            self.curPageNoEdit.setEnabled(False)
        if btnStr == "停止刷新":
            self.refreshSelfBtn.setText("自动刷新")
            self.Refresh_timer.stop()
            self.setBtn.setEnabled(True)
            self.refreshBtn.setEnabled(True)
            self.changePwdBtn.setEnabled(True)
            self.prevPageBtn.setEnabled(True)
            self.nextPageBtn.setEnabled(True)
            self.curPageNoEdit.setEnabled(True)
            self.log_msg(flag=self.INFO, msg_str="停止自动刷新")

    def onClickedChangeBtn_c(self):
        """
        点击确认修改程序
        :return:
        """
        oldPwd = self.changePwdView.oldPwd.text()
        newPwd1 = self.changePwdView.newPwd1.text()
        newPwd2 = self.changePwdView.newPwd2.text()
        if newPwd1 != newPwd2:
            if QMessageBox.warning(self, "提示", "两次输入的新密码不一致!         ", QMessageBox.Ok,
                                   QMessageBox.Ok) == QMessageBox.Ok:
                self.changePwdView.oldPwd.setText("")
                self.changePwdView.newPwd1.setText("")
                self.changePwdView.newPwd2.setText("")
            return
        if len(newPwd1) < 6:
            if QMessageBox.warning(self, "提示", "密码不能少于6个字符!         ", QMessageBox.Ok,
                                   QMessageBox.Ok) == QMessageBox.Ok:
                self.changePwdView.oldPwd.setText("")
                self.changePwdView.newPwd1.setText("")
                self.changePwdView.newPwd2.setText("")
            return

        if oldPwd != self.password:
            if QMessageBox.warning(self, "提示", "原始密码输入错误!         ", QMessageBox.Ok,
                                   QMessageBox.Ok) == QMessageBox.Ok:
                self.changePwdView.oldPwd.setText("")
                self.changePwdView.newPwd1.setText("")
                self.changePwdView.newPwd2.setText("")
            return
        s1 = sha1(newPwd1.encode("utf-8"))
        newPwd1_s1 = s1.hexdigest()
        sqlStr1 = "UPDATE adminuser SET upwd = '%s' WHERE uname = '%s'" % (newPwd1_s1, self.account)
        sqlStr2 = "UPDATE login SET upwd = '%s' WHERE uname = '%s'" % (newPwd1_s1, self.account)
        sqlStr3 = "UPDATE lineuser SET upwd = '%s' WHERE uname = '%s'" % (newPwd1_s1, self.account)
        try:
            self.cursor.execute(sqlStr1)
            self.db.commit()
        except Exception as e1:
            self.log_msg(flag=self.ERROR, msg_str="修改密码异常(001)", msg_tuple=e1)
            self.db.rollback()
            return
        try:
            self.cursor.execute(sqlStr2)
            self.db.commit()
        except Exception as e2:
            self.log_msg(flag=self.ERROR, msg_str="修改密码异常(002)", msg_tuple=e2)
            self.db.rollback()
            return
        try:
            self.cursor.execute(sqlStr3)
            self.db.commit()
        except Exception as e3:
            self.log_msg(flag=self.ERROR, msg_str="修改密码异常(003)", msg_tuple=e3)
            self.db.rollback()
            return
        self.password = newPwd1
        if QMessageBox.warning(self, "提示", "密码修改成功!         ", QMessageBox.Ok,
                               QMessageBox.Ok) == QMessageBox.Ok:
            self.log_msg(flag=self.INFO, msg_str="密码修改成功")
            self.changePwdView.close()

    def refreshSelf(self):
        """
        自动刷新显示列表
        :return:
        """
        ret = self.getSpoolDate(pageNo=self.curPage)
        if ret == -1:
            return
        self.updateTable()
        ret = self.getTotalPage()
        if ret == -1:
            return
        else:
            self.totalPageLable.setText("/%d(共%d页)" % (self.totalPage, self.totalPage))
            self.log_msg(flag=self.INFO, msg_str="页面自动刷新中")

    def scanner_statu_change(self):
        """
        当扫码枪未连接是,闪烁来进行提醒
        :return:
        """
        if self.scanner_statue_flag:
            self.ScanConStatu.setText("扫描枪未连接")
            self.ScanConStatu.setStyleSheet("background:red;border:none;font:bold;font-size:12px")
            self.scanner_statue_flag = False
        else:
            self.ScanConStatu.setText("扫描枪未连接")
            self.ScanConStatu.setStyleSheet("background:none;border:none;font:bold;font-size:12px")
            self.scanner_statue_flag = True

    def plc_statue_change(self):
        if self.plc_statue_flag:
            self.PlcConStatu.setText("PLC未连接")
            self.PlcConStatu.setStyleSheet("background:red;border:none;font:bold;font-size:12px")
            self.plc_statue_flag = False
        else:
            self.PlcConStatu.setText("PLC未连接")
            self.PlcConStatu.setStyleSheet("background:none;border:none;font:bold;font-size:12px")
            self.plc_statue_flag = True

    def changSetBoxColor(self, color):
        """
        修改设置栏文字颜色
        :param color:
        :return:
        """
        if self.isAdmin == True:
            self.machineID.setStyleSheet("color:%s" % color)
            self.plantID.setStyleSheet("color:%s" % color)
            self.processNo.setStyleSheet("color:%s" % color)
            self.localityNo.setStyleSheet("color:%s" % color)
            self.type.setStyleSheet("color:%s" % color)
        self.classBox.setStyleSheet("color:%s" % color)

    def setTable(self):
        """
        设置列表
        :return:
        """
        size = self.showTable.size()
        self.showTable.setColumnWidth(0, size.width() / 12)
        self.showTable.setColumnWidth(1, size.width() / 6)
        self.showTable.setColumnWidth(2, size.width() / 6)
        self.showTable.setColumnWidth(3, size.width() / 6)
        self.showTable.setColumnWidth(4, size.width() / 12)
        self.showTable.setColumnWidth(5, size.width() / 6)
        self.showTable.setColumnWidth(6, size.width() / 6)
        height = self.showTable.horizontalHeader().height()
        for i in range(0, 15):
            self.showTable.setRowHeight(i, (size.height() - height) / 15)

    def updateTable(self):
        """
        更新列表
        :return:
        """
        for i in range(0, 15):
            for j in range(0, 7):
                self.mode.setData(self.mode.index(i, j), "")
        try:
            result = self.cursor.fetchall()
            for i in range(0, len(result)):
                for j in range(0, 7):
                    if j == 0:
                        self.mode.setData(self.mode.index(i, j), str(i + 1))
                    elif j == 4:
                        if result[i][j] == 1:
                            self.mode.setData(self.mode.index(i, j), "是")
                        else:
                            self.mode.setData(self.mode.index(i, j), "否")
                    elif j == 2 or j == 5:
                        self.mode.setData(self.mode.index(i, j), str(result[i][j]))
                    else:
                        self.mode.setData(self.mode.index(i, j), result[i][j])
            self.setTable()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_str="获取数据异常")
        gc.collect()

    def log_msg(self, flag, msg_str=None, msg_tuple=None):
        """
        打包日志信息
        :param flag:信息级别
        :param msg_str: 信息字符串
        :param msg_tuple: 信息数组
        :return:
        """
        if flag == self.DEBUG:
            if msg_str:
                self.log.debug(msg_str)
            if msg_tuple:
                self.log.debug(msg_tuple)
        elif flag == self.INFO:
            if msg_str:
                self.log.info(msg_str)
            if msg_tuple:
                self.log.info(msg_tuple)
        elif flag == self.WARNING:
            if msg_str:
                self.log.warning(msg_str)
            if msg_tuple:
                self.log.warning(msg_tuple)
        elif flag == self.ERROR:
            if msg_str:
                self.log.error(msg_str)
            if msg_tuple:
                self.log.error(msg_tuple)
        elif flag == self.CRITICAL:
            if msg_str:
                self.log.critical(msg_str)
            if msg_tuple:
                self.log.critical(msg_tuple)
        msg = {
            "code": flag,
            "msgstr": msg_str,
            "msgtuple": msg_tuple
        }
        self.msg_append(msg)

    def msg_append(self, msg):
        """
        消息加入消息队列
        :param msg:消息包
        :return:
        """
        # print(msg)
        self.mutex1.lock()
        self.msg_list.append(msg)
        self.mutex1.unlock()
        try:
            for i in self.msg_list:
                self.signal.set()
                time.sleep(0.01)
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_str="消息队列处理异常")

    def getSpoolDate(self, pageSize=15, pageNo=1):
        """
        获取工字轮数据,对应数据库gongzilun表
        :param pageSize:
        :param pageNo:
        :return:
        """
        minRow = (pageNo - 1) * pageSize
        count = pageSize
        sqlStr = "SELECT * FROM gongzilun ORDER BY id DESC LIMIT %d,%d" % (minRow, count)
        try:
            self.cursor.execute(sqlStr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_tuple=e)
            return -1
        return 0

    def getTotalPage(self):
        """
        获取总页数
        :return:
        """
        sqlStr = "SELECT COUNT(*) FROM gongzilun"
        try:
            self.cursor.execute(sqlStr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_tuple=e)
            return -1
        else:
            result = self.cursor.fetchall()
            self.totalPage = math.ceil(result[0][0] / 15)
            return 0

    def updateOnlineDate(self):
        """
        更新登录数据
        :return:
        """
        ret = self.clear_lineuser()
        if ret == -1:
            self.log_msg(flag=self.WARNING, msg_str="在线用户存在异常数据,未清理")
        s1 = sha1(self.password.encode("utf-8"))
        pwd = s1.hexdigest()
        sqlStr = "INSERT INTO lineuser (uname,upwd,denglushijian,runnormal)" \
                 " VALUES ('%s','%s','%s','%s')" % (self.account, pwd, self.loadTimeStr, "True")
        try:
            self.cursor.execute(sqlStr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_str="更新在线账号信息异常", msg_tuple=e)
            self.db.rollback()
            return -1
        return 0

    def clear_lineuser(self):
        """
        用与清除在线用户表中的异常数据
        :return:
        """
        sqlStr = "DELETE FROM lineuser WHERE id > 0"  # WHERE uname = 'admin' OR uname = 'user'
        try:
            self.cursor.execute(sqlStr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_tuple=e)
            return -1
        else:
            return 0

    def getMachineSetDate(self):
        """
        获取设置信息
        :return:
        """
        sqlStr = "SELECT * FROM machine WHERE id = 1"
        try:
            self.cursor.execute(sqlStr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_tuple=e)
            return
        result = self.cursor.fetchall()
        self.machineID.setText(result[0][1])
        self.plantID.setText(result[0][2])
        self.processNo.setText(result[0][3])
        self.localityNo.setText(result[0][4])
        self.type.setText(result[0][5])
        classNo = result[0][6]
        self.classBox.setCurrentIndex(int(classNo))
        self.loadTime.setText(self.loadTimeStr)

    def updataMachineSetDate(self):
        """
        更新设置信息
        :return:
        """
        classNo = self.classBox.currentIndex()
        if self.isAdmin == True:
            machineID = self.machineID.text()
            plantID = self.plantID.text()
            processNo = self.processNo.text()
            localityNo = self.localityNo.text()
            type = self.type.text()
            sqlStr = "UPDATE machine SET shebeiid = '%s',gongchangid = '%s',gongxuid= '%s', \
                     caijidianid = '%s',caijidiantype = '%s',banci = '%s' WHERE id = 1" \
                     % (machineID, plantID, processNo, localityNo, type, str(classNo))
        if self.isAdmin == False:
            sqlStr = "UPDATE machine SET banci = '%s' WHERE id = 1" % str(classNo)
        try:
            self.cursor.execute(sqlStr)
            self.db.commit()
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_tuple=e)
            self.db.rollback()
            return -1
        return 0

    def mouseDoubleClickEvent(self, *args, **kwargs):
        """
        判断鼠标双击位置是窗口状态栏上
        :param args:
        :param kwargs:
        :return:
        """
        statu_lable_rect = self.statuLable.rect()
        statu_lable_width = statu_lable_rect.width()
        statu_lable_height = statu_lable_rect.height()
        statuLable_pos = self.statuLable.mapToGlobal(QPoint(0, 0))
        mouse_pos = args[0].globalPos()
        if statuLable_pos.x() <= mouse_pos.x() < statuLable_pos.x() + statu_lable_width and statuLable_pos.y() < mouse_pos.y() < statuLable_pos.y() + statu_lable_height:
            print("双击状态栏")

    def resizeEvent(self, *args, **kwargs):
        """
        自动调整页面
        :param args:
        :param kwargs:
        :return:
        """
        try:
            oldSize = args[0].oldSize()
            nowSize = args[0].size()
            self.statuLable.setMinimumSize(nowSize.width() / 2 - 10, 12)
            self.nowTimeLable.setMinimumSize(nowSize.width() / 2 - 10, 12)
        except Exception as e:
            self.log_msg(flag=self.ERROR, msg_tuple=e)
        if oldSize != QSize(-1, -1):
            try:
                self.layoutWidget.setGeometry(QRect(0, 10, nowSize.width() - 12, nowSize.height() - 38))
                self.setTable()
            except Exception as e2:
                self.log_msg(flag=self.ERROR, msg_str="窗口大小变动异常", msg_tuple=e2)

    def closeEvent(self, *args, **kwargs):
        """
        程序退出事件
        :param args:
        :param kwargs:
        :return:
        """
        if QMessageBox.warning(self, "提示", "确定要退出程序吗?         ", QMessageBox.Yes | QMessageBox.No,
                               QMessageBox.No) == QMessageBox.Yes:
            sqlStr = "DELETE FROM lineuser WHERE denglushijian = '%s'" % self.loadTimeStr
            try:
                self.cursor.execute(sqlStr)
                self.db.commit()
            except Exception as e:
                self.log_msg(flag=self.ERROR, msg_str="程序退出,清除用户信息异常", msg_tuple=e)
                return
            self.log_msg(flag=self.INFO, msg_str="程序退出")
            time.sleep(0.5)
            self.cursor.close()
            self.db.close()
            self.T1.isStart = False
            self.T1.quit()
            self.T1.wait()
            args[0].accept()
        else:
            args[0].ignore()

    def err_msg_work(self, msg):
        if msg["code"] == 10:  # 连接扫码枪成功
            # QMessageBox.warning(self, "提示", msg["msgstr"], QMessageBox.Yes, QMessageBox.Yes)
            self.ScanConStatu.setText("扫描枪已连接")
            self.ScanConStatu.setStyleSheet("background:#00DD00;border:none;font:bold;font-size:12px")
            self.scanner_statue_timer.stop()
        if msg["code"] == 11:  # 扫码枪未连接
            self.ScanConStatu.setText("扫描枪未连接")
            self.ScanConStatu.setStyleSheet("background:red;border:none;font:bold;font-size:12px")
            self.scanner_statue_timer.start(1000)
        if msg["code"] == 20:  # PLC连接成功
            self.PlcConStatu.setText("PLC已连接")
            self.PlcConStatu.setStyleSheet("background:#00DD00;border:none;font:bold;font-size:12px")
            self.plc_statue_timer.stop()
        if msg["code"] == 21:  # PLC未连接
            self.PlcConStatu.setText("PLC未连接")
            self.PlcConStatu.setStyleSheet("background:red;border:none;font:bold;font-size:12px")
            self.plc_statue_timer.start(1000)
        if msg["code"] == 22:  # 与PLC连接异常断开
            self.PlcConStatu.setText("PLC未连接")
            self.PlcConStatu.setStyleSheet("background:red;border:none;font:bold;font-size:12px")
            self.plc_statue_timer.start(1000)

    def run(self, *args, **kwargs):
        self.loginShow()
        self.q = args[0]
        self.q_err = args[1]
        self.T1 = get_msg_from_sys_thread(self)
        self.T2 = set_status_msg_thread(self)
        self.T3 = get_err_msg_from_sys_thread(self, self.q_err)
        self.T3.signal.connect(self.err_msg_work)
        self.T2.start()
        self.T1.isStart = True
        self.T1.start()
Exemple #14
0
class ReservationSystem(QWidget):
    global currentYear, currentMonth, currentDay

    currentDay = datetime.now().day
    currentMonth = datetime.now().month
    currentYear = datetime.now().year

    dic = {
        'teeth check up': ['Kaisa', 'Teemu', 'Inka'],
        'teeth removal': ['Kaisa', 'Teemu', 'Inka'],
        'teeth whitening': ['Kaisa', 'Teemu', 'Inka'],
        'consultation': ['Kaisa', 'Inka'],
        'implant': ['Inka']
    }

    service_time = {
        'teeth check up': 25,
        'teeth removal': 25,
        'teeth whitening': 25,
        'consultation': 20,
        'implant': 55
    }

    def __init__(self):
        super().__init__()
        self.setWindowTitle('Reservation System')
        self.setGeometry(300, 200, 1000, 800)
        self.model = QStandardItemModel()
        # Calendar
        self.calendar = QtWidgets.QCalendarWidget(self)
        self.calendar.setGeometry(20, 250, 460, 330)
        self.init_calendar()
        # menu bar
        self.menubar = QtWidgets.QMenuBar(self)
        # self.menubar.setGeometry(0, 0, 600, 10)
        self.menuOther_services = QtWidgets.QMenu(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.actionCheck_history = QtWidgets.QAction(self)
        self.actionCheck_history.setText("Get booking records")
        self.menuOther_services.addAction(self.actionCheck_history)
        self.actionCancellation = QtWidgets.QAction(self)
        self.actionCancellation.setText("Cancellation")
        self.menuOther_services.addAction(self.actionCancellation)
        self.menuOther_services.setTitle("Other services")
        self.menubar.addAction(self.menuOther_services.menuAction())
        self.actionCheck_history.triggered.connect(self.history_window)
        self.actionCancellation.triggered.connect(self.cancellation_window)
        # Name
        self.label1 = QtWidgets.QLabel(self)
        self.label1.setText("Name")
        self.label1.setGeometry(20, 50, 200, 20)
        self.name = QtWidgets.QLineEdit(self)
        self.name.setGeometry(20, 70, 200, 20)
        self.name.setPlaceholderText("Enter Your Name")
        # Email
        self.label2 = QtWidgets.QLabel(self)
        self.label2.setText("Email")
        self.label2.setGeometry(260, 50, 200, 20)
        self.email = QtWidgets.QLineEdit(self)
        self.email.setGeometry(260, 70, 200, 20)
        self.email.setPlaceholderText("Enter your Email")
        # Phone
        self.label3 = QtWidgets.QLabel(self)
        self.label3.setText("Phone")
        self.label3.setGeometry(500, 50, 200, 20)
        self.phone = QtWidgets.QLineEdit(self)
        self.phone.setGeometry(500, 70, 200, 20)
        self.phone.setPlaceholderText("Phone number starting with 0")
        # Select Service
        self.label4 = QtWidgets.QLabel(self)
        self.label4.setText("Select Service")
        self.label4.setGeometry(20, 115, 200, 20)
        self.service = QtWidgets.QComboBox(self)
        self.service.setGeometry(20, 145, 200, 30)
        self.service.setModel(self.model)
        # label text 1
        self.label5 = QtWidgets.QLabel(self)
        self.label5.setText(
            "Click on the date and available slots will shown on the right=>\nALWAYS click on the date to REFRESH the "
            "available slots!")
        self.label5.setGeometry(20, 200, 500, 40)
        # Select Doctor
        self.label5 = QtWidgets.QLabel(self)
        self.label5.setText("Select Doctor")
        self.label5.setGeometry(260, 115, 200, 20)
        self.doctor = QtWidgets.QComboBox(self)
        self.doctor.setGeometry(260, 145, 200, 30)
        self.doctor.setModel(self.model)
        # update combobox
        self.update_combobox()
        # time list
        self.listWidget = QtWidgets.QListWidget(self)
        self.listWidget.setGeometry(520, 180, 200, 400)
        # label text 2
        self.label6 = QtWidgets.QLabel(self)
        self.label6.setText("Pick a time below")
        self.label6.setGeometry(515, 140, 180, 20)
        # Button and checkbox
        self.pushButton = QtWidgets.QPushButton(self)
        self.pushButton.setGeometry(240, 660, 80, 30)
        self.pushButton.setText("Reserve")
        self.checkBox = QtWidgets.QCheckBox(self)
        self.checkBox.setGeometry(50, 615, 600, 50)
        self.checkBox.setText(
            "I confirm all information are correct and I want to reserve this time"
        )
        # Reserve time
        self.pushButton.clicked.connect(self.reserve)
        # reminder label in red color
        self.label7 = QtWidgets.QLabel(self)
        self.label7.setGeometry(100, 700, 500, 30)
        # New window after reservation
        self.window = QtWidgets.QMainWindow()
        self.window.resize(550, 300)
        self.window.setWindowTitle("Your booking is complete!")
        self.window.label = QtWidgets.QLabel(self.window)
        self.window.label.setGeometry(55, 30, 450, 200)
        self.show()
        # New window for history
        self.window2 = QtWidgets.QMainWindow()
        self.window2.resize(700, 600)
        self.window2.setWindowTitle("Get booking records")
        self.window2.label = QtWidgets.QLabel(self.window2)
        self.window2.label.setGeometry(20, 10, 650, 40)
        self.window2.label.setText(
            "Please enter your information to check booking records.\nRecords will be returned "
            "only if name and phone are matched with the records")
        # Name 2
        self.window2.label1 = QtWidgets.QLabel(self.window2)
        self.window2.label1.setText("Name")
        self.window2.label1.setGeometry(20, 70, 150, 20)
        self.window2.name = QtWidgets.QLineEdit(self.window2)
        self.window2.name.setGeometry(20, 90, 150, 20)
        self.window2.name.setPlaceholderText("Enter Your Name")
        # Phone 2
        self.window2.label3 = QtWidgets.QLabel(self.window2)
        self.window2.label3.setText("Phone")
        self.window2.label3.setGeometry(200, 70, 150, 20)
        self.window2.phone = QtWidgets.QLineEdit(self.window2)
        self.window2.phone.setGeometry(200, 90, 150, 20)
        self.window2.phone.setPlaceholderText("Phone number")
        # Button and checkbox
        self.window2.pushButton = QtWidgets.QPushButton(self.window2)
        self.window2.pushButton.setGeometry(380, 80, 150, 30)
        self.window2.pushButton.setText("Get records")
        # qtableview
        self.window2.tableWidget = QtWidgets.QTableWidget(self.window2)
        self.window2.tableWidget.setGeometry(10, 140, 500, 400)
        self.window2.labeln = QtWidgets.QLabel(self.window2)
        self.window2.pushButton.clicked.connect(self.display_history)

        # New window if want cancellation
        self.window3 = QtWidgets.QMainWindow()
        self.window3.resize(960, 600)
        self.window3.setWindowTitle("cancellation")
        self.window3.label = QtWidgets.QLabel(self.window3)
        self.window3.label.setGeometry(15, 10, 550, 20)
        self.window3.label.setText(
            "Please enter your information for cancellation.")
        self.window3.label2 = QtWidgets.QLabel(self.window3)
        self.window3.label2.setGeometry(15, 25, 550, 20)
        self.window3.label2.setStyleSheet("color: red")
        self.window3.label2.setText(
            "Please note for cancellation within 24 hours, you will be charged 40€!"
        )
        self.window3.label3 = QtWidgets.QLabel(self.window3)
        self.window3.label3.setGeometry(600, 20, 550, 100)
        self.window3.label3.setText(
            "Select the time you would like\n to cancel by checking the 'Cancel' box.\nOnce the "
            "below button is clicked, \nyour cancellation request will be handled"
        )
        # Name
        self.window3.label1 = QtWidgets.QLabel(self.window3)
        self.window3.label1.setText("Name")
        self.window3.label1.setGeometry(20, 70, 150, 20)
        self.window3.name = QtWidgets.QLineEdit(self.window3)
        self.window3.name.setGeometry(20, 90, 150, 20)
        self.window3.name.setPlaceholderText("Enter Your Name")
        # Phone
        self.window3.label3 = QtWidgets.QLabel(self.window3)
        self.window3.label3.setText("Phone")
        self.window3.label3.setGeometry(200, 70, 150, 20)
        self.window3.phone = QtWidgets.QLineEdit(self.window3)
        self.window3.phone.setGeometry(200, 90, 150, 20)
        self.window3.phone.setPlaceholderText("Phone number")
        # Button
        self.window3.pushButton = QtWidgets.QPushButton(self.window3)
        self.window3.pushButton.setGeometry(380, 80, 120, 30)
        self.window3.pushButton.setText("Search/Refresh")
        # qtableview
        self.window3.tableWidget = QtWidgets.QTableWidget(self.window3)
        self.window3.tableWidget.setGeometry(5, 140, 600, 400)
        self.window3.labeln = QtWidgets.QLabel(self.window3)
        # cancellation button
        self.window3.cancel = QtWidgets.QPushButton(self.window3)
        self.window3.cancel.setGeometry(640, 150, 150, 30)
        self.window3.cancel.setText("Confirm Cancel")
        # Cancelation confirmation text
        self.window3.label4 = QtWidgets.QLabel(self.window3)
        self.window3.label4.setGeometry(620, 190, 350, 60)
        self.window3.pushButton.clicked.connect(self.cancellation)
        self.window3.cancel.clicked.connect(self.cancellation_click)

    def history_window(self):
        self.window2.labeln.clear()
        self.window2.name.clear()
        self.window2.phone.clear()
        self.window2.tableWidget.clear()
        self.window2.show()

    def cancellation_window(self):
        self.window3.name.clear()
        self.window3.phone.clear()
        self.window3.labeln.clear()
        self.window3.label4.clear()
        self.window3.tableWidget.clear()
        self.window3.show()

    def cancellation_click(self):
        name = self.window3.name.text()
        phone = "'" + self.window3.phone.text()
        c = Customer(name, phone)
        for i in range(self.window3.tableWidget.rowCount()):
            item = self.window3.tableWidget.item(
                i,
                self.window3.tableWidget.columnCount() - 1)
            if item.checkState() != 0:
                date = self.window3.tableWidget.item(item.row(), 0)
                time = self.window3.tableWidget.item(item.row(), 1)
                doctor = self.window3.tableWidget.item(item.row(), 2)
                service = self.window3.tableWidget.item(item.row(), 3)
                txt = c.cancel(date.text(), time.text(), service.text(),
                               doctor.text())
                self.window3.label4.setText(
                    txt + '\nhit search/refresh to refresh booking records!')

    def display_history(self):
        self.window2.tableWidget.clear()
        name = self.window2.name.text()
        phone = "'" + self.window2.phone.text()
        df = Customer.get_booked(name, phone)
        if isinstance(df, pd.DataFrame):
            self.window2.labeln.clear()
            df = df[[
                'Reserved date', 'Reserved time', 'Reserved doctor',
                'Reserved service'
            ]].drop_duplicates()
            df = df.sort_values(['Reserved date', 'Reserved time'],
                                ascending=[True, True])
            self.window2.tableWidget.setRowCount(df.shape[0])
            self.window2.tableWidget.setColumnCount(df.shape[1])
            for i in range(df.shape[0]):
                for j in range(df.shape[1]):
                    item = QtWidgets.QTableWidgetItem(str(df.iloc[i, j]))
                    self.window2.tableWidget.setItem(i, j, item)
            self.window2.tableWidget.setHorizontalHeaderLabels(
                df.columns.tolist())
        else:
            self.window2.labeln.setText(
                "Record not found! Please input valid name and phone!")
            self.window2.labeln.setStyleSheet("color: red")
            self.window2.labeln.setGeometry(40, 114, 400, 20)

    def cancellation(self):
        self.window3.labeln.clear()
        self.window3.tableWidget.clear()
        self.window3.label4.clear()
        name = self.window3.name.text()
        phone = "'" + self.window3.phone.text()
        df = Customer.get_future_events(name, phone)
        if isinstance(df, pd.DataFrame):
            self.window3.labeln.clear()
            df = df[[
                'Reserved date', 'Reserved time', 'Reserved doctor',
                'Reserved service'
            ]].drop_duplicates()
            df = df.sort_values(['Reserved date', 'Reserved time'],
                                ascending=[True, True])
            self.window3.tableWidget.setRowCount(df.shape[0])
            self.window3.tableWidget.setColumnCount(df.shape[1])
            for i in range(df.shape[0]):
                for j in range(df.shape[1]):
                    item = QtWidgets.QTableWidgetItem(str(df.iloc[i, j]))
                    self.window3.tableWidget.setItem(i, j, item)
            # add one column for checkbox
            self.window3.tableWidget.insertColumn(df.shape[1])
            for i in range(df.shape[0]):
                chkBoxItem = QtWidgets.QTableWidgetItem()
                chkBoxItem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                chkBoxItem.setCheckState(QtCore.Qt.Unchecked)
                self.window3.tableWidget.setItem(i, df.shape[1], chkBoxItem)
            self.window3.tableWidget.setHorizontalHeaderLabels(
                df.columns.tolist() + ['Cancel'])
        else:
            self.window3.labeln.setText("There is no upcoming bookings!")
            self.window3.labeln.setStyleSheet("color: red")
            self.window3.labeln.setGeometry(40, 114, 400, 20)

    @staticmethod
    def input_checkup(name, email, phone):
        if all([substring in email for substring in ['.', '@']]) and any(
                x.isalpha() for x in name) and phone[1:].isnumeric():
            return True

    def reserve(self):
        if self.checkBox.isChecked():
            self.label7.clear()
            name = self.name.text()
            email = self.email.text()
            phone = "'" + self.phone.text()
            service = self.service.currentText()
            doctor = self.doctor.currentText()
            date = '{2}-{0}-{1}'.format(self.calendar.selectedDate().month(),
                                        self.calendar.selectedDate().day(),
                                        self.calendar.selectedDate().year())
            item = self.listWidget.currentItem()
            if name is not None and email is not None and phone is not None and self.input_checkup(
                    name, email, phone):
                if item is not None:
                    time = item.text()
                    c = Customer(name, phone, email)
                    a = c.reserve(date, time, service, doctor)
                    if a is None:
                        # self.close()
                        self.window.label.clear()
                        self.window.label.setText(
                            f"{service}:\n{time} on {date} \nwith doctor {doctor} is confirmed!\nThank you!:)"
                        )
                        font = QFont()
                        font.setPointSize(16)
                        self.window.label.setFont(font)
                        self.window.show()
                    else:
                        txt = a + ' Please choose a new time!'
                        self.label7.setText(a)

                else:
                    self.label7.setText(
                        'Please select a date and time for booking!')
                    self.label7.setStyleSheet("color: red")
            else:
                self.label7.setText(
                    'Some information is not correct or missing!')
                self.label7.setStyleSheet("color: red")
        else:
            self.label7.setText(
                "Please confirm your booking by checking the checkbox!")
            self.label7.setStyleSheet("color: red")

    def update_combobox(self):
        for k, v in self.dic.items():
            service = QStandardItem(k)
            self.model.appendRow(service)
            for value in v:
                doctor = QStandardItem(value)
                service.appendRow(doctor)
        self.service.currentIndexChanged.connect(self.update_service)
        self.update_service(0)

    def update_service(self, index):
        index = self.model.index(index, 0, self.service.rootModelIndex())
        self.doctor.setRootModelIndex(index)
        self.doctor.setCurrentIndex(0)

    def init_calendar(self):
        self.calendar.setGridVisible(True)
        self.calendar.setMinimumDate(
            QDate(currentYear, currentMonth, currentDay))
        self.calendar.setMaximumDate(
            QDate(currentYear, currentMonth + 1,
                  calendar.monthrange(currentYear, currentMonth)[1]))
        self.calendar.setSelectedDate(QDate(currentYear, currentMonth, 1))
        self.calendar.clicked.connect(self.get_time)

    def get_time(self, QDate):
        doctor_name = self.doctor.currentText()
        service_name = self.service.currentText()
        duration = self.service_time[service_name]
        a = Doctor(doctor_name)
        date = '{2}-{0}-{1}'.format(QDate.month(), QDate.day(), QDate.year())
        self.listWidget.clear()
        if pd.to_datetime(date).weekday() < 5:
            if pd.to_datetime(date) > datetime.today():
                for i in a.show_available_slots(date, service_name):
                    time = (datetime.strptime(i, '%H:%M') +
                            timedelta(minutes=duration))
                    end_time = datetime.strftime(time, '%H:%M')
                    item = i + ' - ' + end_time
                    self.listWidget.addItem(item)
            else:
                x = [
                    datetime.strptime(i, '%H:%M')
                    for i in a.show_available_slots(date, service_name)
                ]
                x = [j for j in x if datetime.now().time() < j.time()]
                x = [datetime.strftime(i, '%H:%M') for i in x]
                for i in x:
                    time = (datetime.strptime(i, '%H:%M') +
                            timedelta(minutes=duration))
                    end_time = datetime.strftime(time, '%H:%M')
                    item = i + ' - ' + end_time
                    self.listWidget.addItem(item)
Exemple #15
0
class MainWindow(QMainWindow):
    def __init__(self,system):
        super(MainWindow, self).__init__()

        self.system = system
        fileMenu = QMenu("&Menu", self)
        dbinitAction = fileMenu.addAction("사용자 정보 초기화")
        quitAction = fileMenu.addAction("E&xit")
        quitAction.setShortcut("Ctrl+Q")

        self.menuBar().addMenu(fileMenu)
        self.statusBar()

        dbinitAction.triggered.connect(self.ClickAction_dbinit)
        quitAction.triggered.connect(QApplication.instance().quit)

        self.setupModel()
        self.setupViews()
        self.readDB()



        self.setWindowTitle("PyStudy 학습진도창")
        self.resize(870, 550)

    def setupModel(self):
        self.model = QStandardItemModel(3, 2, self)
        self.model.setHeaderData(0, Qt.Horizontal, "목록")
        self.model.setHeaderData(1, Qt.Horizontal, "읽기여부")
        self.model2 = QStandardItemModel(3, 2, self)
        self.model2.setHeaderData(0, Qt.Horizontal, "학습여부")
        self.model2.setHeaderData(1, Qt.Horizontal, "개수")


    def setupViews(self):
        splitter = QSplitter()
        self.table = QTableView()
        self.pieChart = PieView()


        splitter.addWidget(self.pieChart)
        splitter.addWidget(self.table)
        splitter.setStretchFactor(0, 0)
        splitter.setStretchFactor(1, 0)

        self.table.setModel(self.model)
        self.pieChart.setModel(self.model2)

        self.selectionModel = QItemSelectionModel(self.model2)
        self.table.setSelectionModel(self.selectionModel)

        #self.pieChart.setSelectionModel(self.selectionModel)

        #table.setColumnWidth(0,100)
        self.setCentralWidget(splitter)
        self.table.doubleClicked.connect(self.ClickAction_table)

    def readDB(self):

        con = sqlite3.connect("mystudy.db")
        cur = con.cursor()
        cur.execute("select subject, readcheck from study;")
        self.model.removeRows(0, self.model.rowCount(QModelIndex()),
                        QModelIndex())
        self.model2.removeRows(0, self.model2.rowCount(QModelIndex()),
                        QModelIndex())
        row = 0
        for line in cur:
            if line[1] ==1:
                result = "○"
            else:
                result = "X"
            self.model.insertRows(row, 1, QModelIndex())
            self.model.setData(self.model.index(row, 0, QModelIndex()), line[0])
            self.model.setData(self.model.index(row, 1, QModelIndex()),result)
            self.model.setData(self.model.index(row, 1, QModelIndex()), QVariant(Qt.AlignCenter),Qt.TextAlignmentRole)
            row += 1
        cur.execute("select count() from study ;")
        for line in cur:
            self.studyTotal =line[0]
        cur.execute("select count() from study where readcheck=1;")
        for line in cur:
            self.studyRead =line[0]
        #print("총 개수 " ,self.studyTotal ," 학습한개수", self.studyRead )
        con.close()
        row=0
        self.model2.insertRows(row, 1, QModelIndex())
        self.model2.setData(self.model2.index(row, 0, QModelIndex()),"학습")
        self.model2.setData(self.model2.index(row, 1, QModelIndex()), float(self.studyRead))
        self.model2.setData(self.model2.index(row, 0, QModelIndex()), QColor("#99e600"), Qt.DecorationRole)
        row=1
        self.model2.insertRows(row, 1, QModelIndex())
        self.model2.setData(self.model2.index(row, 0, QModelIndex()),"미학습")
        self.model2.setData(self.model2.index(row, 1, QModelIndex()), float(self.studyTotal-self.studyRead))
        self.model2.setData(self.model2.index(row, 0, QModelIndex()), QColor("#8080b3"), Qt.DecorationRole)


        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.setDragEnabled(False)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.resizeRowsToContents()
        self.table.resizeColumnsToContents()
        self.table.setColumnWidth(0,350)
                    #self.statusBar().showMessage("Loaded %s" % path, 2000)
    def ClickAction_table(self,index):
        #self.system
        #index.data()
        #self.table.selectedIndexes()[0].data()
        tempstr = self.table.selectedIndexes()[0].data().split()
        filepath = r"PyStudy_web\\example\\기본예제\\"+tempstr[0]+".html"
        selectedRowKey = self.table.selectedIndexes()[0].row()+1#mysql 테이블 줄수 차이
        #print("click test ",selectedRowKey )
        con = sqlite3.connect("mystudy.db")
        cur = con.cursor()
        cur.execute("update 'study' set 'readcheck'=1 where key="+str(selectedRowKey)+";")
        con.commit()
        con.close()
        self.setupViews()
        self.readDB()

        self.system.sendMessage("/학습창 열기 "+filepath)
    def ClickAction_dbinit(self,index):
        con = sqlite3.connect("mystudy.db")
        cur = con.cursor()
        cur.execute("update 'study' set 'readcheck'=0 ;")
        con.commit()
        con.close()
        self.setupViews()
        self.readDB()
Exemple #16
0
class MainWindow(QMainWindow, Ui_MainWindow):
    dictChanged = pyqtSignal(str)

    # Tab indexes
    TabInfos = 0
    TabSummary = 1
    TabPersos = 2
    TabPlots = 3
    TabWorld = 4
    TabOutline = 5
    TabRedac = 6

    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)
        self.currentProject = None

        self.readSettings()

        # UI
        self.setupMoreUi()

        # Welcome
        self.welcome.updateValues()
        # self.welcome.btnCreate.clicked.connect
        self.stack.setCurrentIndex(0)

        # Word count
        self.mprWordCount = QSignalMapper(self)
        for t, i in [
            (self.txtSummarySentence, 0),
            (self.txtSummaryPara, 1),
            (self.txtSummaryPage, 2),
            (self.txtSummaryFull, 3)
        ]:
            t.textChanged.connect(self.mprWordCount.map)
            self.mprWordCount.setMapping(t, i)
        self.mprWordCount.mapped.connect(self.wordCount)

        # Snowflake Method Cycle
        self.mapperCycle = QSignalMapper(self)
        for t, i in [
            (self.btnStepTwo, 0),
            (self.btnStepThree, 1),
            (self.btnStepFour, 2),
            (self.btnStepFive, 3),
            (self.btnStepSix, 4),
            (self.btnStepSeven, 5),
            (self.btnStepEight, 6)
        ]:
            t.clicked.connect(self.mapperCycle.map)
            self.mapperCycle.setMapping(t, i)

        self.mapperCycle.mapped.connect(self.clickCycle)
        self.cmbSummary.currentIndexChanged.connect(self.summaryPageChanged)
        self.cmbSummary.setCurrentIndex(0)
        self.cmbSummary.currentIndexChanged.emit(0)

        # Main Menu
        for i in [self.actSave, self.actSaveAs, self.actCloseProject,
                  self.menuEdit, self.menuMode, self.menuView, self.menuTools,
                  self.menuHelp]:
            i.setEnabled(False)

        self.actOpen.triggered.connect(self.welcome.openFile)
        self.actSave.triggered.connect(self.saveDatas)
        self.actSaveAs.triggered.connect(self.welcome.saveAsFile)
        self.actCompile.triggered.connect(self.doCompile)
        self.actLabels.triggered.connect(self.settingsLabel)
        self.actStatus.triggered.connect(self.settingsStatus)
        self.actSettings.triggered.connect(self.settingsWindow)
        self.actCloseProject.triggered.connect(self.closeProject)
        self.actQuit.triggered.connect(self.close)
        self.actToolFrequency.triggered.connect(self.frequencyAnalyzer)
        self.generateViewMenu()

        self.makeUIConnections()

        # self.loadProject(os.path.join(appPath(), "test_project.zip"))

    ###############################################################################
    # SUMMARY
    ###############################################################################

    def summaryPageChanged(self, index):
        fractalButtons = [
            self.btnStepTwo,
            self.btnStepThree,
            self.btnStepFive,
            self.btnStepSeven,
        ]
        for b in fractalButtons:
            b.setVisible(fractalButtons.index(b) == index)

    ###############################################################################
    # OUTLINE
    ###############################################################################

    def outlineRemoveItemsRedac(self):
        self.treeRedacOutline.delete()

    def outlineRemoveItemsOutline(self):
        self.treeOutlineOutline.delete()

    ###############################################################################
    # PERSOS
    ###############################################################################

    def changeCurrentPerso(self, trash=None):

        index = self.lstPersos.currentPersoIndex()

        if not index.isValid():
            self.tabPlot.setEnabled(False)
            return

        self.tabPersos.setEnabled(True)

        for w in [
            self.txtPersoName,
            self.sldPersoImportance,
            self.txtPersoMotivation,
            self.txtPersoGoal,
            self.txtPersoConflict,
            self.txtPersoEpiphany,
            self.txtPersoSummarySentence,
            self.txtPersoSummaryPara,
            self.txtPersoSummaryFull,
            self.txtPersoNotes,
        ]:
            w.setCurrentModelIndex(index)

        # Button color
        self.mdlPersos.updatePersoColor(index)

        # Perso Infos
        self.tblPersoInfos.setRootIndex(index)

        if self.mdlPersos.rowCount(index):
            self.updatePersoInfoView()

    def updatePersoInfoView(self):
        # Hide columns
        for i in range(self.mdlPersos.columnCount()):
            self.tblPersoInfos.hideColumn(i)
        self.tblPersoInfos.showColumn(Perso.infoName.value)
        self.tblPersoInfos.showColumn(Perso.infoData.value)

        self.tblPersoInfos.horizontalHeader().setSectionResizeMode(
                Perso.infoName.value, QHeaderView.ResizeToContents)
        self.tblPersoInfos.horizontalHeader().setSectionResizeMode(
                Perso.infoData.value, QHeaderView.Stretch)
        self.tblPersoInfos.verticalHeader().hide()

    ###############################################################################
    # PLOTS
    ###############################################################################

    def changeCurrentPlot(self):
        index = self.lstPlots.currentPlotIndex()

        if not index.isValid():
            self.tabPlot.setEnabled(False)
            return

        self.tabPlot.setEnabled(True)
        self.txtPlotName.setCurrentModelIndex(index)
        self.txtPlotDescription.setCurrentModelIndex(index)
        self.txtPlotResult.setCurrentModelIndex(index)
        self.sldPlotImportance.setCurrentModelIndex(index)
        self.lstPlotPerso.setRootIndex(index.sibling(index.row(),
                                                     Plot.persos.value))
        subplotindex = index.sibling(index.row(), Plot.subplots.value)
        self.lstSubPlots.setRootIndex(subplotindex)
        if self.mdlPlots.rowCount(subplotindex):
            self.updateSubPlotView()

        # self.txtSubPlotSummary.setCurrentModelIndex(QModelIndex())
        self.txtSubPlotSummary.setEnabled(False)
        self._updatingSubPlot = True
        self.txtSubPlotSummary.setPlainText("")
        self._updatingSubPlot = False
        self.lstPlotPerso.selectionModel().clear()

    def updateSubPlotView(self):
        # Hide columns
        for i in range(self.mdlPlots.columnCount()):
            self.lstSubPlots.hideColumn(i)
        self.lstSubPlots.showColumn(Subplot.name.value)
        self.lstSubPlots.showColumn(Subplot.meta.value)

        self.lstSubPlots.horizontalHeader().setSectionResizeMode(
                Subplot.name.value, QHeaderView.Stretch)
        self.lstSubPlots.horizontalHeader().setSectionResizeMode(
                Subplot.meta.value, QHeaderView.ResizeToContents)
        self.lstSubPlots.verticalHeader().hide()

    def changeCurrentSubPlot(self, index):
        # Got segfaults when using textEditView model system, so ad hoc stuff.
        index = index.sibling(index.row(), Subplot.summary.value)
        item = self.mdlPlots.itemFromIndex(index)
        if not item:
            self.txtSubPlotSummary.setEnabled(False)
            return
        self.txtSubPlotSummary.setEnabled(True)
        txt = item.text()
        self._updatingSubPlot = True
        self.txtSubPlotSummary.setPlainText(txt)
        self._updatingSubPlot = False

    def updateSubPlotSummary(self):
        if self._updatingSubPlot:
            return

        index = self.lstSubPlots.currentIndex()
        if not index.isValid():
            return
        index = index.sibling(index.row(), Subplot.summary.value)
        item = self.mdlPlots.itemFromIndex(index)

        self._updatingSubPlot = True
        item.setText(self.txtSubPlotSummary.toPlainText())
        self._updatingSubPlot = False

    def plotPersoSelectionChanged(self):
        "Enables or disables remove plot perso button."
        self.btnRmPlotPerso.setEnabled(
                len(self.lstPlotPerso.selectedIndexes()) != 0)

    ###############################################################################
    # WORLD
    ###############################################################################

    def changeCurrentWorld(self):
        index = self.mdlWorld.selectedIndex()

        if not index.isValid():
            self.tabWorld.setEnabled(False)
            return

        self.tabWorld.setEnabled(True)
        self.txtWorldName.setCurrentModelIndex(index)
        self.txtWorldDescription.setCurrentModelIndex(index)
        self.txtWorldPassion.setCurrentModelIndex(index)
        self.txtWorldConflict.setCurrentModelIndex(index)

    ###############################################################################
    # LOAD AND SAVE
    ###############################################################################

    def loadProject(self, project, loadFromFile=True):
        """Loads the project ``project``.

        If ``loadFromFile`` is False, then it does not load datas from file.
        It assumes that the datas have been populated in a different way."""
        if loadFromFile and not os.path.exists(project):
            print(self.tr("The file {} does not exist. Try again.").format(project))
            self.statusBar().showMessage(
                    self.tr("The file {} does not exist. Try again.").format(project),
                    5000)
            return

        if loadFromFile:
            # Load empty settings
            imp.reload(settings)

            # Load data
            self.loadEmptyDatas()
            self.loadDatas(project)

        self.makeConnections()

        # Load settings
        for i in settings.openIndexes:
            idx = self.mdlOutline.indexFromPath(i)
            self.mainEditor.setCurrentModelIndex(idx, newTab=True)
        self.generateViewMenu()
        self.mainEditor.sldCorkSizeFactor.setValue(settings.corkSizeFactor)
        self.actSpellcheck.setChecked(settings.spellcheck)
        self.toggleSpellcheck(settings.spellcheck)
        self.updateMenuDict()
        self.setDictionary()

        self.mainEditor.setFolderView(settings.folderView)
        self.mainEditor.updateFolderViewButtons(settings.folderView)
        self.tabMain.setCurrentIndex(settings.lastTab)
        # We force to emit even if it opens on the current tab
        self.tabMain.currentChanged.emit(settings.lastTab)
        self.mainEditor.updateCorkBackground()

        # Set autosave
        self.saveTimer = QTimer()
        self.saveTimer.setInterval(settings.autoSaveDelay * 60 * 1000)
        self.saveTimer.setSingleShot(False)
        self.saveTimer.timeout.connect(self.saveDatas)
        if settings.autoSave:
            self.saveTimer.start()

        # Set autosave if no changes
        self.saveTimerNoChanges = QTimer()
        self.saveTimerNoChanges.setInterval(settings.autoSaveNoChangesDelay * 1000)
        self.saveTimerNoChanges.setSingleShot(True)
        self.mdlFlatData.dataChanged.connect(self.startTimerNoChanges)
        self.mdlOutline.dataChanged.connect(self.startTimerNoChanges)
        self.mdlPersos.dataChanged.connect(self.startTimerNoChanges)
        self.mdlPlots.dataChanged.connect(self.startTimerNoChanges)
        self.mdlWorld.dataChanged.connect(self.startTimerNoChanges)
        # self.mdlPersosInfos.dataChanged.connect(self.startTimerNoChanges)
        self.mdlStatus.dataChanged.connect(self.startTimerNoChanges)
        self.mdlLabels.dataChanged.connect(self.startTimerNoChanges)

        self.saveTimerNoChanges.timeout.connect(self.saveDatas)
        self.saveTimerNoChanges.stop()

        # UI
        for i in [self.actSave, self.actSaveAs, self.actCloseProject,
                  self.menuEdit, self.menuMode, self.menuView, self.menuTools,
                  self.menuHelp]:
            i.setEnabled(True)
        # FIXME: set Window's name: project name

        # Stuff
        # self.checkPersosID()  # Should'n be necessary any longer

        self.currentProject = project
        QSettings().setValue("lastProject", project)

        # Show main Window
        self.stack.setCurrentIndex(1)

    def closeProject(self):
        # Save datas
        self.saveDatas()

        self.currentProject = None
        QSettings().setValue("lastProject", "")

        # FIXME: close all opened tabs in mainEditor

        # Clear datas
        self.loadEmptyDatas()

        self.saveTimer.stop()

        # UI
        for i in [self.actSave, self.actSaveAs, self.actCloseProject,
                  self.menuEdit, self.menuMode, self.menuView, self.menuTools,
                  self.menuHelp]:
            i.setEnabled(False)

        # Reload recent files
        self.welcome.updateValues()

        # Show welcome dialog
        self.stack.setCurrentIndex(0)

    def readSettings(self):
        # Load State and geometry
        sttgns = QSettings(qApp.organizationName(), qApp.applicationName())
        if sttgns.contains("geometry"):
            self.restoreGeometry(sttgns.value("geometry"))
        if sttgns.contains("windowState"):
            self.restoreState(sttgns.value("windowState"))
        else:
            self.dckCheatSheet.hide()
            self.dckSearch.hide()
        if sttgns.contains("metadataState"):
            state = [False if v == "false" else True for v in sttgns.value("metadataState")]
            self.redacMetadata.restoreState(state)
        if sttgns.contains("revisionsState"):
            state = [False if v == "false" else True for v in sttgns.value("revisionsState")]
            self.redacMetadata.revisions.restoreState(state)
        if sttgns.contains("splitterRedacH"):
            self.splitterRedacH.restoreState(sttgns.value("splitterRedacH"))
        if sttgns.contains("splitterRedacV"):
            self.splitterRedacV.restoreState(sttgns.value("splitterRedacV"))
        if sttgns.contains("toolbar"):
            # self.toolbar is not initialized yet, so we just store balue
            self._toolbarState = sttgns.value("toolbar")
        else:
            self._toolbarState = ""


    def closeEvent(self, event):
        # Save State and geometry and other things
        sttgns = QSettings(qApp.organizationName(), qApp.applicationName())
        sttgns.setValue("geometry", self.saveGeometry())
        sttgns.setValue("windowState", self.saveState())
        sttgns.setValue("metadataState", self.redacMetadata.saveState())
        sttgns.setValue("revisionsState", self.redacMetadata.revisions.saveState())
        sttgns.setValue("splitterRedacH", self.splitterRedacH.saveState())
        sttgns.setValue("splitterRedacV", self.splitterRedacV.saveState())
        sttgns.setValue("toolbar", self.toolbar.saveState())

        # Specific settings to save before quitting
        settings.lastTab = self.tabMain.currentIndex()

        if self.currentProject:
            # Remembering the current items
            sel = []
            for i in range(self.mainEditor.tab.count()):
                sel.append(self.mdlOutline.pathToIndex(self.mainEditor.tab.widget(i).currentIndex))
            settings.openIndexes = sel

        # Save data from models
        if self.currentProject and settings.saveOnQuit:
            self.saveDatas()

            # closeEvent
            # QMainWindow.closeEvent(self, event)  # Causin segfaults?

    def startTimerNoChanges(self):
        if settings.autoSaveNoChanges:
            self.saveTimerNoChanges.start()

    def saveDatas(self, projectName=None):
        """Saves the current project (in self.currentProject).

        If ``projectName`` is given, currentProject becomes projectName.
        In other words, it "saves as...".
        """

        if projectName:
            self.currentProject = projectName
            QSettings().setValue("lastProject", projectName)

        # Saving
        files = []

        files.append((saveStandardItemModelXML(self.mdlFlatData),
                      "flatModel.xml"))
        files.append((saveStandardItemModelXML(self.mdlPersos),
                      "perso.xml"))
        files.append((saveStandardItemModelXML(self.mdlWorld),
                      "world.xml"))
        files.append((saveStandardItemModelXML(self.mdlLabels),
                      "labels.xml"))
        files.append((saveStandardItemModelXML(self.mdlStatus),
                      "status.xml"))
        files.append((saveStandardItemModelXML(self.mdlPlots),
                      "plots.xml"))
        files.append((self.mdlOutline.saveToXML(),
                      "outline.xml"))
        files.append((settings.save(),
                      "settings.pickle"))

        saveFilesToZip(files, self.currentProject)

        # Giving some feedback
        print(self.tr("Project {} saved.").format(self.currentProject))
        self.statusBar().showMessage(
                self.tr("Project {} saved.").format(self.currentProject), 5000)

    def loadEmptyDatas(self):
        self.mdlFlatData = QStandardItemModel(self)
        self.mdlPersos = persosModel(self)
        # self.mdlPersosProxy = persosProxyModel(self)
        # self.mdlPersosInfos = QStandardItemModel(self)
        self.mdlLabels = QStandardItemModel(self)
        self.mdlStatus = QStandardItemModel(self)
        self.mdlPlots = plotModel(self)
        self.mdlOutline = outlineModel(self)
        self.mdlWorld = worldModel(self)

    def loadDatas(self, project):
        # Loading
        files = loadFilesFromZip(project)

        errors = []

        if "flatModel.xml" in files:
            loadStandardItemModelXML(self.mdlFlatData,
                                     files["flatModel.xml"], fromString=True)
        else:
            errors.append("flatModel.xml")

        if "perso.xml" in files:
            loadStandardItemModelXML(self.mdlPersos,
                                     files["perso.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "world.xml" in files:
            loadStandardItemModelXML(self.mdlWorld,
                                     files["world.xml"], fromString=True)
        else:
            errors.append("world.xml")

        if "labels.xml" in files:
            loadStandardItemModelXML(self.mdlLabels,
                                     files["labels.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "status.xml" in files:
            loadStandardItemModelXML(self.mdlStatus,
                                     files["status.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "plots.xml" in files:
            loadStandardItemModelXML(self.mdlPlots,
                                     files["plots.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "outline.xml" in files:
            self.mdlOutline.loadFromXML(files["outline.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "settings.pickle" in files:
            settings.load(files["settings.pickle"], fromString=True)
        else:
            errors.append("perso.xml")

        # Giving some feedback
        if not errors:
            print(self.tr("Project {} loaded.").format(project))
            self.statusBar().showMessage(
                    self.tr("Project {} loaded.").format(project), 5000)
        else:
            print(self.tr("Project {} loaded with some errors:").format(project))
            for e in errors:
                print(self.tr(" * {} wasn't found in project file.").format(e))
            self.statusBar().showMessage(
                    self.tr("Project {} loaded with some errors.").format(project), 5000)

    ###############################################################################
    # MAIN CONNECTIONS
    ###############################################################################

    def makeUIConnections(self):
        "Connections that have to be made once only, event when new project is loaded."
        self.lstPersos.currentItemChanged.connect(self.changeCurrentPerso, AUC)

        self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter, AUC)
        self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot, AUC)
        self.txtSubPlotSummary.document().contentsChanged.connect(
                self.updateSubPlotSummary, AUC)
        self.lstSubPlots.activated.connect(self.changeCurrentSubPlot, AUC)

        self.btnRedacAddFolder.clicked.connect(self.treeRedacOutline.addFolder, AUC)
        self.btnOutlineAddFolder.clicked.connect(self.treeOutlineOutline.addFolder, AUC)
        self.btnRedacAddText.clicked.connect(self.treeRedacOutline.addText, AUC)
        self.btnOutlineAddText.clicked.connect(self.treeOutlineOutline.addText, AUC)
        self.btnRedacRemoveItem.clicked.connect(self.outlineRemoveItemsRedac, AUC)
        self.btnOutlineRemoveItem.clicked.connect(self.outlineRemoveItemsOutline, AUC)

        self.tabMain.currentChanged.connect(self.toolbar.setCurrentGroup)

    def makeConnections(self):

        # Flat datas (Summary and general infos)
        for widget, col in [
            (self.txtSummarySituation, 0),
            (self.txtSummarySentence, 1),
            (self.txtSummarySentence_2, 1),
            (self.txtSummaryPara, 2),
            (self.txtSummaryPara_2, 2),
            (self.txtPlotSummaryPara, 2),
            (self.txtSummaryPage, 3),
            (self.txtSummaryPage_2, 3),
            (self.txtPlotSummaryPage, 3),
            (self.txtSummaryFull, 4),
            (self.txtPlotSummaryFull, 4),
        ]:
            widget.setModel(self.mdlFlatData)
            widget.setColumn(col)
            widget.setCurrentModelIndex(self.mdlFlatData.index(1, col))

        for widget, col in [
            (self.txtGeneralTitle, 0),
            (self.txtGeneralSubtitle, 1),
            (self.txtGeneralSerie, 2),
            (self.txtGeneralVolume, 3),
            (self.txtGeneralGenre, 4),
            (self.txtGeneralLicense, 5),
            (self.txtGeneralAuthor, 6),
            (self.txtGeneralEmail, 7),
        ]:
            widget.setModel(self.mdlFlatData)
            widget.setColumn(col)
            widget.setCurrentModelIndex(self.mdlFlatData.index(0, col))

        # Persos
        self.lstPersos.setPersosModel(self.mdlPersos)
        self.tblPersoInfos.setModel(self.mdlPersos)

        self.btnAddPerso.clicked.connect(self.mdlPersos.addPerso, AUC)
        self.btnRmPerso.clicked.connect(self.mdlPersos.removePerso, AUC)
        self.btnPersoColor.clicked.connect(self.mdlPersos.chosePersoColor, AUC)

        self.btnPersoAddInfo.clicked.connect(self.mdlPersos.addPersoInfo, AUC)
        self.btnPersoRmInfo.clicked.connect(self.mdlPersos.removePersoInfo, AUC)

        for w, c in [
            (self.txtPersoName, Perso.name.value),
            (self.sldPersoImportance, Perso.importance.value),
            (self.txtPersoMotivation, Perso.motivation.value),
            (self.txtPersoGoal, Perso.goal.value),
            (self.txtPersoConflict, Perso.conflict.value),
            (self.txtPersoEpiphany, Perso.epiphany.value),
            (self.txtPersoSummarySentence, Perso.summarySentence.value),
            (self.txtPersoSummaryPara, Perso.summaryPara.value),
            (self.txtPersoSummaryFull, Perso.summaryFull.value),
            (self.txtPersoNotes, Perso.notes.value)
        ]:
            w.setModel(self.mdlPersos)
            w.setColumn(c)
        self.tabPersos.setEnabled(False)

        # Plots
        self.lstPlots.setPlotModel(self.mdlPlots)
        self.lstPlotPerso.setModel(self.mdlPlots)
        self.lstSubPlots.setModel(self.mdlPlots)
        self._updatingSubPlot = False
        self.btnAddPlot.clicked.connect(self.mdlPlots.addPlot, AUC)
        self.btnRmPlot.clicked.connect(lambda:
                                       self.mdlPlots.removePlot(self.lstPlots.currentPlotIndex()), AUC)
        self.btnAddSubPlot.clicked.connect(self.mdlPlots.addSubPlot, AUC)
        self.btnRmSubPlot.clicked.connect(self.mdlPlots.removeSubPlot, AUC)
        self.lstPlotPerso.selectionModel().selectionChanged.connect(self.plotPersoSelectionChanged)
        self.btnRmPlotPerso.clicked.connect(self.mdlPlots.removePlotPerso, AUC)

        for w, c in [
            (self.txtPlotName, Plot.name.value),
            (self.txtPlotDescription, Plot.description.value),
            (self.txtPlotResult, Plot.result.value),
            (self.sldPlotImportance, Plot.importance.value),
        ]:
            w.setModel(self.mdlPlots)
            w.setColumn(c)

        self.tabPlot.setEnabled(False)
        self.mdlPlots.updatePlotPersoButton()
        self.mdlPersos.dataChanged.connect(self.mdlPlots.updatePlotPersoButton)
        self.lstOutlinePlots.setPlotModel(self.mdlPlots)
        self.lstOutlinePlots.setShowSubPlot(True)
        self.plotPersoDelegate = outlinePersoDelegate(self.mdlPersos, self)
        self.lstPlotPerso.setItemDelegate(self.plotPersoDelegate)
        self.plotDelegate = plotDelegate(self)
        self.lstSubPlots.setItemDelegateForColumn(Subplot.meta.value, self.plotDelegate)

        # World
        self.treeWorld.setModel(self.mdlWorld)
        for i in range(self.mdlWorld.columnCount()):
            self.treeWorld.hideColumn(i)
        self.treeWorld.showColumn(0)
        self.btnWorldEmptyData.setMenu(self.mdlWorld.emptyDataMenu())
        self.treeWorld.selectionModel().selectionChanged.connect(self.changeCurrentWorld, AUC)
        self.btnAddWorld.clicked.connect(self.mdlWorld.addItem, AUC)
        self.btnRmWorld.clicked.connect(self.mdlWorld.removeItem, AUC)
        for w, c in [
            (self.txtWorldName, World.name.value),
            (self.txtWorldDescription, World.description.value),
            (self.txtWorldPassion, World.passion.value),
            (self.txtWorldConflict, World.conflict.value),
        ]:
            w.setModel(self.mdlWorld)
            w.setColumn(c)
        self.tabWorld.setEnabled(False)
        self.treeWorld.expandAll()

        # Outline
        self.treeRedacOutline.setModel(self.mdlOutline)
        self.treeOutlineOutline.setModelPersos(self.mdlPersos)
        self.treeOutlineOutline.setModelLabels(self.mdlLabels)
        self.treeOutlineOutline.setModelStatus(self.mdlStatus)

        self.redacMetadata.setModels(self.mdlOutline, self.mdlPersos,
                                     self.mdlLabels, self.mdlStatus)
        self.outlineItemEditor.setModels(self.mdlOutline, self.mdlPersos,
                                         self.mdlLabels, self.mdlStatus)

        self.treeOutlineOutline.setModel(self.mdlOutline)
        # self.redacEditor.setModel(self.mdlOutline)
        self.storylineView.setModels(self.mdlOutline, self.mdlPersos, self.mdlPlots)

        self.treeOutlineOutline.selectionModel().selectionChanged.connect(lambda:
                                                                          self.outlineItemEditor.selectionChanged(
                                                                                  self.treeOutlineOutline), AUC)
        self.treeOutlineOutline.clicked.connect(lambda:
                                                self.outlineItemEditor.selectionChanged(self.treeOutlineOutline), AUC)

        # Sync selection
        self.treeRedacOutline.selectionModel().selectionChanged.connect(
                lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline), AUC)
        self.treeRedacOutline.clicked.connect(
                lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline), AUC)

        self.treeRedacOutline.selectionModel().selectionChanged.connect(self.mainEditor.selectionChanged, AUC)

        # Cheat Sheet
        self.cheatSheet.setModels()

        # Debug
        self.mdlFlatData.setVerticalHeaderLabels(["Infos générales", "Summary"])
        self.tblDebugFlatData.setModel(self.mdlFlatData)
        self.tblDebugPersos.setModel(self.mdlPersos)
        self.tblDebugPersosInfos.setModel(self.mdlPersos)
        self.tblDebugPersos.selectionModel().currentChanged.connect(
                lambda: self.tblDebugPersosInfos.setRootIndex(self.mdlPersos.index(
                        self.tblDebugPersos.selectionModel().currentIndex().row(),
                        Perso.name.value)), AUC)

        self.tblDebugPlots.setModel(self.mdlPlots)
        self.tblDebugPlotsPersos.setModel(self.mdlPlots)
        self.tblDebugSubPlots.setModel(self.mdlPlots)
        self.tblDebugPlots.selectionModel().currentChanged.connect(
                lambda: self.tblDebugPlotsPersos.setRootIndex(self.mdlPlots.index(
                        self.tblDebugPlots.selectionModel().currentIndex().row(),
                        Plot.persos.value)), AUC)
        self.tblDebugPlots.selectionModel().currentChanged.connect(
                lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index(
                        self.tblDebugPlots.selectionModel().currentIndex().row(),
                        Plot.subplots.value)), AUC)
        self.treeDebugWorld.setModel(self.mdlWorld)
        self.treeDebugOutline.setModel(self.mdlOutline)
        self.lstDebugLabels.setModel(self.mdlLabels)
        self.lstDebugStatus.setModel(self.mdlStatus)

    ###############################################################################
    # GENERAL AKA UNSORTED
    ###############################################################################

    def clickCycle(self, i):
        if i == 0:  # step 2 - paragraph summary
            self.tabMain.setCurrentIndex(self.TabSummary)
            self.tabSummary.setCurrentIndex(1)
        if i == 1:  # step 3 - characters summary
            self.tabMain.setCurrentIndex(self.TabPersos)
            self.tabPersos.setCurrentIndex(0)
        if i == 2:  # step 4 - page summary
            self.tabMain.setCurrentIndex(self.TabSummary)
            self.tabSummary.setCurrentIndex(2)
        if i == 3:  # step 5 - characters description
            self.tabMain.setCurrentIndex(self.TabPersos)
            self.tabPersos.setCurrentIndex(1)
        if i == 4:  # step 6 - four page synopsis
            self.tabMain.setCurrentIndex(self.TabSummary)
            self.tabSummary.setCurrentIndex(3)
        if i == 5:  # step 7 - full character charts
            self.tabMain.setCurrentIndex(self.TabPersos)
            self.tabPersos.setCurrentIndex(2)
        if i == 6:  # step 8 - scene list
            self.tabMain.setCurrentIndex(self.TabPlots)

    def wordCount(self, i):

        src = {
            0: self.txtSummarySentence,
            1: self.txtSummaryPara,
            2: self.txtSummaryPage,
            3: self.txtSummaryFull
        }[i]

        lbl = {
            0: self.lblSummaryWCSentence,
            1: self.lblSummaryWCPara,
            2: self.lblSummaryWCPage,
            3: self.lblSummaryWCFull
        }[i]

        wc = wordCount(src.toPlainText())
        if i in [2, 3]:
            pages = self.tr(" (~{} pages)").format(int(wc / 25) / 10.)
        else:
            pages = ""
        lbl.setText(self.tr("Words: {}{}").format(wc, pages))

    def setupMoreUi(self):

        # Tool bar on the right
        self.toolbar = collapsibleDockWidgets(Qt.RightDockWidgetArea, self)
        self.toolbar.addCustomWidget(self.tr("Book summary"), self.grpPlotSummary, self.TabPlots)
        self.toolbar.addCustomWidget(self.tr("Project tree"), self.treeRedacWidget, self.TabRedac)
        self.toolbar.addCustomWidget(self.tr("Metadata"), self.redacMetadata, self.TabRedac)
        self.toolbar.addCustomWidget(self.tr("Story line"), self.storylineView, self.TabRedac)
        if self._toolbarState:
            self.toolbar.restoreState(self._toolbarState)

        # Custom "tab" bar on the left
        self.lstTabs.setIconSize(QSize(48, 48))
        for i in range(self.tabMain.count()):
            icons = ["general-128px.png",
                     "summary-128px.png",
                     "characters-128px.png",
                     "plot-128px.png",
                     "world-128px.png",
                     "outline-128px.png",
                     "redaction-128px.png",
                     ""
                     ]
            self.tabMain.setTabIcon(i, QIcon(appPath("icons/Custom/Tabs/{}".format(icons[i]))))
            item = QListWidgetItem(self.tabMain.tabIcon(i),
                                   self.tabMain.tabText(i))
            item.setSizeHint(QSize(item.sizeHint().width(), 64))
            item.setTextAlignment(Qt.AlignCenter)
            self.lstTabs.addItem(item)
        self.tabMain.tabBar().hide()
        self.lstTabs.currentRowChanged.connect(self.tabMain.setCurrentIndex)
        self.tabMain.currentChanged.connect(self.lstTabs.setCurrentRow)

        # Splitters
        self.splitterPersos.setStretchFactor(0, 25)
        self.splitterPersos.setStretchFactor(1, 75)

        self.splitterPlot.setStretchFactor(0, 20)
        self.splitterPlot.setStretchFactor(1, 60)
        self.splitterPlot.setStretchFactor(2, 30)

        self.splitterWorld.setStretchFactor(0, 25)
        self.splitterWorld.setStretchFactor(1, 75)

        self.splitterOutlineH.setStretchFactor(0, 25)
        self.splitterOutlineH.setStretchFactor(1, 75)
        self.splitterOutlineV.setStretchFactor(0, 75)
        self.splitterOutlineV.setStretchFactor(1, 25)

        self.splitterRedacV.setStretchFactor(0, 75)
        self.splitterRedacV.setStretchFactor(1, 25)

        self.splitterRedacH.setStretchFactor(0, 30)
        self.splitterRedacH.setStretchFactor(1, 40)
        self.splitterRedacH.setStretchFactor(2, 30)

        # QFormLayout stretch
        for w in [self.txtWorldDescription, self.txtWorldPassion, self.txtWorldConflict]:
            s = w.sizePolicy()
            s.setVerticalStretch(1)
            w.setSizePolicy(s)

        # Help box
        references = [
            (self.lytTabOverview,
             self.tr("Enter infos about your book, and yourself."),
             0),
            (self.lytSituation,
             self.tr(
                     """The basic situation, in the form of a 'What if...?' question. Ex: 'What if the most dangerous
                     evil wizard could wasn't abled to kill a baby?' (Harry Potter)"""),
             1),
            (self.lytSummary,
             self.tr(
                     """Take time to think about a one sentence (~50 words) summary of your book. Then expand it to
                     a paragraph, then to a page, then to a full summary."""),
             1),
            (self.lytTabPersos,
             self.tr("Create your characters."),
             0),
            (self.lytTabPlot,
             self.tr("Develop plots."),
             0),
            (self.lytTabOutline,
             self.tr("Create the outline of your masterpiece."),
             0),
            (self.lytTabRedac,
             self.tr("Write."),
             0),
            (self.lytTabDebug,
             self.tr("Debug infos. Sometimes useful."),
             0)
        ]

        for widget, text, pos in references:
            label = helpLabel(text, self)
            self.actShowHelp.toggled.connect(label.setVisible, AUC)
            widget.layout().insertWidget(pos, label)

        self.actShowHelp.setChecked(False)

        # Spellcheck
        if enchant:
            self.menuDict = QMenu(self.tr("Dictionary"))
            self.menuDictGroup = QActionGroup(self)
            self.updateMenuDict()
            self.menuTools.addMenu(self.menuDict)

            self.actSpellcheck.toggled.connect(self.toggleSpellcheck, AUC)
            self.dictChanged.connect(self.mainEditor.setDict, AUC)
            self.dictChanged.connect(self.redacMetadata.setDict, AUC)
            self.dictChanged.connect(self.outlineItemEditor.setDict, AUC)

        else:
            # No Spell check support
            self.actSpellcheck.setVisible(False)
            a = QAction(self.tr("Install PyEnchant to use spellcheck"), self)
            a.setIcon(self.style().standardIcon(QStyle.SP_MessageBoxWarning))
            a.triggered.connect(self.openPyEnchantWebPage, AUC)
            self.menuTools.addAction(a)

    ###############################################################################
    # SPELLCHECK
    ###############################################################################

    def updateMenuDict(self):

        if not enchant:
            return

        self.menuDict.clear()
        for i in enchant.list_dicts():
            a = QAction(str(i[0]), self)
            a.setCheckable(True)
            if settings.dict is None:
                settings.dict = enchant.get_default_language()
            if str(i[0]) == settings.dict:
                a.setChecked(True)
            a.triggered.connect(self.setDictionary, AUC)
            self.menuDictGroup.addAction(a)
            self.menuDict.addAction(a)

    def setDictionary(self):
        if not enchant:
            return

        for i in self.menuDictGroup.actions():
            if i.isChecked():
                # self.dictChanged.emit(i.text().replace("&", ""))
                settings.dict = i.text().replace("&", "")

                # Find all textEditView from self, and toggle spellcheck
                for w in self.findChildren(textEditView, QRegExp(".*"),
                                           Qt.FindChildrenRecursively):
                    w.setDict(settings.dict)

    def openPyEnchantWebPage(self):
        from PyQt5.QtGui import QDesktopServices
        QDesktopServices.openUrl(QUrl("http://pythonhosted.org/pyenchant/"))

    def toggleSpellcheck(self, val):
        settings.spellcheck = val

        # Find all textEditView from self, and toggle spellcheck
        for w in self.findChildren(textEditView, QRegExp(".*"),
                                   Qt.FindChildrenRecursively):
            w.toggleSpellcheck(val)

    ###############################################################################
    # SETTINGS
    ###############################################################################

    def settingsLabel(self):
        self.settingsWindow(3)

    def settingsStatus(self):
        self.settingsWindow(4)

    def settingsWindow(self, tab=None):
        self.sw = settingsWindow(self)
        self.sw.hide()
        self.sw.setWindowModality(Qt.ApplicationModal)
        self.sw.setWindowFlags(Qt.Dialog)
        r = self.sw.geometry()
        r2 = self.geometry()
        self.sw.move(r2.center() - r.center())
        if tab:
            self.sw.setTab(tab)
        self.sw.show()

    ###############################################################################
    # TOOLS
    ###############################################################################

    def frequencyAnalyzer(self):
        self.fw = frequencyAnalyzer(self)
        self.fw.show()

    ###############################################################################
    # VIEW MENU
    ###############################################################################

    def generateViewMenu(self):

        values = [
            (self.tr("Nothing"), "Nothing"),
            (self.tr("POV"), "POV"),
            (self.tr("Label"), "Label"),
            (self.tr("Progress"), "Progress"),
            (self.tr("Compile"), "Compile"),
        ]

        menus = [
            (self.tr("Tree"), "Tree"),
            (self.tr("Index cards"), "Cork"),
            (self.tr("Outline"), "Outline")
        ]

        submenus = {
            "Tree": [
                (self.tr("Icon color"), "Icon"),
                (self.tr("Text color"), "Text"),
                (self.tr("Background color"), "Background"),
            ],
            "Cork": [
                (self.tr("Icon"), "Icon"),
                (self.tr("Text"), "Text"),
                (self.tr("Background"), "Background"),
                (self.tr("Border"), "Border"),
                (self.tr("Corner"), "Corner"),
            ],
            "Outline": [
                (self.tr("Icon color"), "Icon"),
                (self.tr("Text color"), "Text"),
                (self.tr("Background color"), "Background"),
            ],
        }

        self.menuView.clear()

        # print("Generating menus with", settings.viewSettings)

        for mnu, mnud in menus:
            m = QMenu(mnu, self.menuView)
            for s, sd in submenus[mnud]:
                m2 = QMenu(s, m)
                agp = QActionGroup(m2)
                for v, vd in values:
                    a = QAction(v, m)
                    a.setCheckable(True)
                    a.setData("{},{},{}".format(mnud, sd, vd))
                    if settings.viewSettings[mnud][sd] == vd:
                        a.setChecked(True)
                    a.triggered.connect(self.setViewSettingsAction, AUC)
                    agp.addAction(a)
                    m2.addAction(a)
                m.addMenu(m2)
            self.menuView.addMenu(m)

    def setViewSettingsAction(self):
        action = self.sender()
        item, part, element = action.data().split(",")
        self.setViewSettings(item, part, element)

    def setViewSettings(self, item, part, element):
        settings.viewSettings[item][part] = element
        if item == "Cork":
            self.mainEditor.updateCorkView()
        if item == "Outline":
            self.mainEditor.updateTreeView()
            self.treeOutlineOutline.viewport().update()
        if item == "Tree":
            self.treeRedacOutline.viewport().update()

    ###############################################################################
    # COMPILE
    ###############################################################################

    def doCompile(self):
        self.compileDialog = compileDialog()
        self.compileDialog.show()
Exemple #17
0
class E5NetworkMonitor(QDialog, Ui_E5NetworkMonitor):
    """
    Class implementing a network monitor dialog.
    """
    _monitor = None
    
    @classmethod
    def instance(cls, networkAccessManager):
        """
        Class method to get a reference to our singleton.
        
        @param networkAccessManager reference to the network access manager
            (QNetworkAccessManager)
        @return reference to the network monitor singleton (E5NetworkMonitor)
        """
        if cls._monitor is None:
            cls._monitor = E5NetworkMonitor(networkAccessManager)
        
        return cls._monitor
    
    @classmethod
    def closeMonitor(cls):
        """
        Class method to close the monitor dialog.
        """
        if cls._monitor is not None:
            cls._monitor.close()
    
    def __init__(self, networkAccessManager, parent=None):
        """
        Constructor
        
        @param networkAccessManager reference to the network access manager
            (QNetworkAccessManager)
        @param parent reference to the parent widget (QWidget)
        """
        super(E5NetworkMonitor, self).__init__(parent)
        self.setupUi(self)
        
        self.__requestHeaders = QStandardItemModel(self)
        self.__requestHeaders.setHorizontalHeaderLabels(
            [self.tr("Name"), self.tr("Value")])
        self.requestHeadersList.setModel(self.__requestHeaders)
        self.requestHeadersList.horizontalHeader().setStretchLastSection(True)
        self.requestHeadersList.doubleClicked.connect(self.__showHeaderDetails)
        
        self.__replyHeaders = QStandardItemModel(self)
        self.__replyHeaders.setHorizontalHeaderLabels(
            [self.tr("Name"), self.tr("Value")])
        self.responseHeadersList.setModel(self.__replyHeaders)
        self.responseHeadersList.horizontalHeader().setStretchLastSection(True)
        self.responseHeadersList.doubleClicked.connect(
            self.__showHeaderDetails)
        
        self.requestsList.horizontalHeader().setStretchLastSection(True)
        self.requestsList.verticalHeader().setMinimumSectionSize(-1)
        
        self.__proxyModel = QSortFilterProxyModel(self)
        self.__proxyModel.setFilterKeyColumn(-1)
        self.searchEdit.textChanged.connect(
            self.__proxyModel.setFilterFixedString)
        
        self.removeButton.clicked.connect(self.requestsList.removeSelected)
        self.removeAllButton.clicked.connect(self.requestsList.removeAll)
        
        self.__model = E5RequestModel(networkAccessManager, self)
        self.__proxyModel.setSourceModel(self.__model)
        self.requestsList.setModel(self.__proxyModel)
        self.__proxyModel.rowsInserted.connect(
            self.requestsList.scrollToBottom)
        self.requestsList.selectionModel()\
            .currentChanged[QModelIndex, QModelIndex]\
            .connect(self.__currentChanged)
        
        fm = self.fontMetrics()
        em = fm.width("m")
        self.requestsList.horizontalHeader().resizeSection(0, em * 5)
        self.requestsList.horizontalHeader().resizeSection(1, em * 20)
        self.requestsList.horizontalHeader().resizeSection(3, em * 5)
        self.requestsList.horizontalHeader().resizeSection(4, em * 15)
        
        self.__headersDlg = None
    
    def closeEvent(self, evt):
        """
        Protected method called upon closing the dialog.
        
        @param evt reference to the close event object (QCloseEvent)
        """
        self.__class__._monitor = None
        super(E5NetworkMonitor, self).closeEvent(evt)
    
    def reject(self):
        """
        Public slot to close the dialog with a Reject status.
        """
        self.__class__._monitor = None
        super(E5NetworkMonitor, self).reject()
    
    def __currentChanged(self, current, previous):
        """
        Private slot to handle a change of the current index.
        
        @param current new current index (QModelIndex)
        @param previous old current index (QModelIndex)
        """
        self.__requestHeaders.setRowCount(0)
        self.__replyHeaders.setRowCount(0)
        
        if not current.isValid():
            return
        
        row = self.__proxyModel.mapToSource(current).row()
        
        req = self.__model.requests[row].request
        
        for header in req.rawHeaderList():
            self.__requestHeaders.insertRows(0, 1, QModelIndex())
            self.__requestHeaders.setData(
                self.__requestHeaders.index(0, 0),
                str(header, "utf-8"))
            self.__requestHeaders.setData(
                self.__requestHeaders.index(0, 1),
                str(req.rawHeader(header), "utf-8"))
            self.__requestHeaders.item(0, 0).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.__requestHeaders.item(0, 1).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        
        for header in self.__model.requests[row].replyHeaders:
            self.__replyHeaders.insertRows(0, 1, QModelIndex())
            self.__replyHeaders.setData(
                self.__replyHeaders.index(0, 0),
                header[0])
            self.__replyHeaders.setData(
                self.__replyHeaders.index(0, 1),
                header[1])
            self.__replyHeaders.item(0, 0).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.__replyHeaders.item(0, 1).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
    
    def __showHeaderDetails(self, index):
        """
        Private slot to show a dialog with the header details.
        
        @param index index of the entry to show (QModelIndex)
        """
        if not index.isValid():
            return
        
        headerList = self.sender()
        if headerList is None:
            return
        
        row = index.row()
        name = headerList.model().data(headerList.model().index(row, 0))
        value = headerList.model().data(headerList.model().index(row, 1))
        if self.__headersDlg is None:
            from .E5NetworkHeaderDetailsDialog import \
                E5NetworkHeaderDetailsDialog
            self.__headersDlg = E5NetworkHeaderDetailsDialog(self)
        self.__headersDlg.setData(name, value)
        self.__headersDlg.show()
Exemple #18
0
class TIM(QWidget, Ui_Form_For_Main):
    grouplist = []
    userslist = []
    tmpuseritem = []
    groupInfo = {}
    chatWindow = {}
    groupChatWindow = {}
    my_groups = []  #Save my group
    glist = []  #Save all information for each group

    def __init__(self, client):
        super().__init__()
        self.m_drag = False
        self.m_DragPosition = QPoint()
        self.cache = Cache(self)
        self.setupUi(self)
        self.client = client
        self.Ui_init()
        self.menuflag = 1
        self.temp = {}
        self.groupTemp = []  #New group id
        self.addTemp = []  #Join the group id

        self.setStyleSheet(open('styles/style5.qss').read())
        self.setWindowIcon(QIcon('img/bubbles-alt-icon.png'))

        palette = QPalette()
        palette.setBrush(self.backgroundRole(),
                         QtGui.QBrush(QtGui.QPixmap('img/background/bg1.jpg')))
        self.setPalette(palette)

        self.setWindowFlag(Qt.FramelessWindowHint)
        self.tray = MySystemTray(self)

        self.listener = Listener(self)
        self.listener.newSysMsgSignal.connect(self.cache.newSysMsg)
        self.listener.newFriendMsgSignal.connect(self.newFriendMsg)
        self.listener.newGroupMsgSignal.connect(self.newGroupMsg)
        self.listener.successAddFriendSignal.connect(self.successAddFriend)
        self.listener.friendOfflineSignal.connect(self.dealFriendOffline)
        self.listener.friendsOnlineSignal.connect(self.dealFriendOnline)
        self.listener.noExistSignal.connect(self.noExist)
        self.listener.offlineSignal.connect(self.offline)
        self.listener.beDelSignal.connect(self.dealBeDel)
        self.listener.createGroupOkSignal.connect(self.dealCreateGroupOk)
        self.listener.addGroupOkSignal.connect(self.dealAddGroupOk)
        self.listener.start()

    def Ui_init(self):
        image = QImage()
        image.loadFromData(self.client.head)
        self.lblHead.setScaledContents(True)
        self.lblHead.setPixmap(QPixmap.fromImage(image))
        self.lblName.setText(self.client.name)
        self.lblId.setText(str(self.client.id))
        self.bt_search.setIcon(QIcon('img/search.png'))
        self.minBt.setIcon(QIcon('img/min.png'))
        self.closeBt.setIcon(QIcon('img/wclose.png'))
        self.setupBt.setIcon(QIcon('img/setting.png'))
        self.bt_adduser.setIcon(QIcon('img/add.png'))
        self.cacheBt.setIcon(QIcon('img/msg.png'))
        self.groupBt.setIcon(QIcon('img/群组.png'))
        self.faceBt.setIcon(QIcon("img/face.png"))
        self.lblIcon.setPixmap(QPixmap('img/chat.png'))
        self.tabWidget.setStyleSheet("background-color:rgba(255,255,255,0.7)")
        self.treeWidget.setStyleSheet("background-color:rgba(255,255,255,0)")
        self.groups.setStyleSheet("background-color:rgba(255,255,255,0)")
        self.groupList.setStyleSheet("background-color:rgba(255,255,255,0)")
        self.friendList.setStyleSheet("background-color:rgba(255,255,255,0)")

        self.m_model = QStandardItemModel(0, 1, self)
        m_completer = QCompleter(self.m_model, self)
        self.lineEdit.setCompleter(m_completer)

        m_completer.activated[str].connect(self.onUsernameChoosed)
        self.setupBt.clicked.connect(self.setUp)
        self.closeBt.clicked.connect(self.close)
        self.minBt.clicked.connect(self.showMinimized)
        self.cacheBt.clicked.connect(self.msgCache)
        self.groupBt.clicked.connect(self.addGroup)
        self.faceBt.clicked.connect(self.changeFace)
        self.treeWidget.currentItemChanged.connect(self.restatistic)
        self.treeWidget.itemClicked.connect(self.isclick)
        self.bt_adduser.clicked.connect(self.on_bt_adduser_clicked)
        self.bt_search.clicked.connect(self.on_bt_search_clicked)
        self.lineEdit.textChanged[str].connect(self.on_lineEdit_textChanged)
        self.treeWidget.itemDoubleClicked.connect(
            self.cache.responseFriendItemClicked)
        self.groups.itemDoubleClicked.connect(
            self.cache.responseGroupItemClicked)

        self.treeWidget.setIndentation(0)
        self.treeWidget.setColumnCount(1)
        self.treeWidget.setColumnWidth(0, 50)
        self.treeWidget.setHeaderLabels(['Friend'])
        self.treeWidget.header().hide()
        self.treeWidget.setIconSize(QSize(70, 70))
        self.treeWidget.setFocusPolicy(Qt.NoFocus)
        self.treeWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.treeWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.creategroup()
        self.initGroup()

    def closeWindow(self):
        if self.cache.isVisible() == True:
            self.cache.close()
        for i in self.chatWindow.keys():
            self.chatWindow[i].close()
        for i in self.groupChatWindow.keys():
            self.groupChatWindow[i].close()

    def dealCreateGroupOk(self, gid, data):
        gname = data.decode('utf-8')
        for info in self.groupTemp:
            if gname == info[0]:
                ghead = info[1]
                newG = Group(gname, gid, ghead, [self.client.id])
                item = QListWidgetItem(self.groups)
                item.setSizeHint(QSize(self.groups.width(), 61))
                self.groups.setItemWidget(item, newG)
                self.groupTemp.remove(info)
                self.my_groups.append(gid)
                groupdic = {
                    'group': item,
                    'groupid': gid,
                    'groupname': gname,
                    'grouphead': ghead,
                    'groupmember': [self.client.id]
                }
                self.glist.append(groupdic)
                break

    def dealAddGroupOk(self, gid, data):
        if gid in self.addTemp:
            data = data.split('\n'.encode('utf-8'), 2)
            gname = data[0].decode('utf-8')
            gmembers = json.loads(data[1].decode('utf-8'))
            ghead = data[2]
            item = QListWidgetItem(self.groups)
            item.setSizeHint(QSize(self.groups.width(), 61))
            newG = Group(gname, gid, ghead, gmembers)
            self.groups.setItemWidget(item, newG)
            self.addTemp.remove(gid)
            self.my_groups.append(gid)

            groupdic = {
                'group': item,
                'groupid': gid,
                'groupname': gname,
                'grouphead': ghead,
                'groupmember': gmembers
            }
            self.glist.append(groupdic)

    def newGroupMsg(self, groupid, type, data):
        if groupid in self.groupChatWindow.keys(
        ) and self.groupChatWindow[groupid].isVisible():
            if (type == Type.GROUP_TEXT):
                self.groupChatWindow[groupid].recviveMsg(data.decode('utf-8'))
            else:
                self.groupChatWindow[groupid].recvivePic(data)
        else:
            self.cache.newGroupMsg(groupid, type, data)

    def newFriendMsg(self, id, type, data):
        if type == Type.FILE:
            for user in self.userslist:
                if id == user['userid']:
                    name = user['username']
                    break
            filename, file = data.split('\n'.encode('utf-8'), 1)
            filename = filename.decode('utf-8')
            response = QMessageBox.question(
                None, "Message",
                "Friend %s (%s) Send file %s,Would you like to accept it?" %
                (name, id, filename), QMessageBox.Yes | QMessageBox.No,
                QMessageBox.Yes)
            if response == QMessageBox.Yes:
                filepath = QFileDialog.getSaveFileName(None, 'Save as',
                                                       './' + filename, '')
                if filepath[0]:
                    with open(filepath[0], 'wb') as f:
                        f.write(file)
                    self.client.dealAcceptFile(id, filename)
                else:
                    self.client.dealRefuseFile(id, filename)
            else:
                self.client.dealRefuseFile(id, filename)
        elif type == Type.FILE_AC:
            for user in self.userslist:
                if id == user['userid']:
                    name = user['username']
                    break
            QMessageBox.information(
                None, 'Message', 'Friend %s (%s) Received file %s' %
                (name, id, data.decode('utf-8')))
        elif type == Type.FILE_RF:
            for user in self.userslist:
                if id == user['userid']:
                    name = user['username']
                    break
            QMessageBox.information(
                None, 'Message',
                'Friend %s (%s) 拒绝接收文件 %s' % (name, id, data.decode('utf-8')))
        else:
            if id in self.chatWindow.keys() and self.chatWindow[id].isVisible(
            ):
                if type == Type.TEXT:
                    self.chatWindow[id].recviveMsg(data.decode('utf-8'))
                elif type == Type.PIC:
                    self.chatWindow[id].recvivePic(data)
            else:
                self.cache.newFriendMsg(id, type, data)

    def sendGroupMsg(self, id, text):
        self.client.dealSendGroupMsg(id, text)

    def sendGroupPic(self, id, pic):
        self.client.dealSendGroupPic(id, pic)

    def sendMsg(self, id, text):
        index = self.searchuser(id)
        if self.userslist[index]['ishide'] == 1:
            self.chatWindow[id].notOnline()
        else:
            self.client.dealSendMsg(id, text)

    def sendPic(self, id, bytes):
        index = self.searchuser(id)
        if self.userslist[index]['ishide'] == 1:
            self.chatWindow[id].notOnline()
        else:
            self.client.dealSendPic(id, bytes)

    def sendFile(self, id, filename):
        index = self.searchuser(id)
        if self.userslist[index]['ishide'] == 1:
            self.chatWindow[id].notOnline()
        else:
            self.client.dealSendFile(id, filename)

    def initGroup(self):  #格式{群id:[群成员id]}?? #grouplist格式为:列表[群id]
        self.my_groups = groupInfo = self.client.dealGetGroupList()
        for groupid in groupInfo:
            groupname, grouphead = self.client.dealGetGroupNameAndHead(groupid)
            groupmember = self.client.dealGetGroupMember(groupid)
            group = QListWidgetItem(self.groups)
            group.setSizeHint(QSize(self.groups.width(), 55))
            groupdic = {
                'group': group,
                'groupid': groupid,
                'groupname': groupname,
                'grouphead': grouphead,
                'groupmember': groupmember
            }

            g = Group(groupname, str(groupid), grouphead, groupmember)
            self.glist.append(groupdic)
            self.groups.setItemWidget(group, g)

    def addGroup(self):
        addG = AddGroup(self.my_groups, self.groupTemp, self.addTemp)
        response = addG.exec_()
        if response == 1:
            gname, ghead = self.groupTemp[-1]
            self.client.dealCreateGroup(gname, ghead)
        elif response == 2:
            gid = self.addTemp[-1]
            self.client.dealJoinGroup(gid)

    def changeFace(self):
        file = QFileDialog.getOpenFileName(self, 'Select background', '.',
                                           ("Images (*.png *.jpg *.bmp)"))
        if file[0]:
            palette = QPalette()
            palette.setBrush(self.backgroundRole(),
                             QtGui.QBrush(QtGui.QPixmap(file[0])))
            self.setPalette(palette)

    def noExist(self, id):
        QMessageBox.information(self, 'Prompt',
                                'There is no account number %s User!' % (id))
        for k, v in self.temp.items():
            if k == id:
                self.temp.pop(k)
                break

    def dealBeDel(self, id):
        dindex = self.searchuser(id)
        ishide = self.userslist[dindex]['ishide']
        delitem = self.userslist[dindex]['user']
        pindex = delitem.parent().indexOfChild(delitem)
        name = self.userslist[dindex]['username']
        del self.userslist[dindex]
        fathergroup = delitem.parent()
        findex = self.searchgroup(fathergroup)
        parentName = self.grouplist[findex]['groupname']
        if ishide == 1:
            self.grouplist[findex]['childishide'] -= 1
            self.grouplist[findex]['childcount'] -= 1
        else:
            self.grouplist[findex]['childcount'] -= 1
        delitem.parent().takeChild(pindex)
        for user in self.groupInfo[parentName]:
            if user['userid'] == id:
                self.groupInfo[parentName].remove(user)
                break

    def offline(self, id):
        QMessageBox.information(
            self, 'Prompt',
            'Account number is %s Users are not online!' % (id))
        for k, v in self.temp.items():
            if k == id:
                self.temp.pop(k)
                break

    def dealRefuseAdd(self, id):
        QMessageBox.information(
            self, 'Prompt',
            'Account number is %s User rejects your friend request!' % id)
        for k, v in self.temp.items():
            if k == id:
                self.temp.pop(k)
                break

    def dealFriendOnline(self, id):
        useritemindex = self.searchuser(id)
        if useritemindex is not None:
            self.userslist[useritemindex]['ishide'] = 0
            useritem = self.userslist[useritemindex]['user']
            parent = useritem.parent()
            findex = self.searchgroup(parent)
            widget = self.treeWidget.itemWidget(useritem, 0)
            widget.lblonlinestate.setPixmap(QPixmap("img/bullet_green.png"))
            self.grouplist[findex]['childishide'] -= 1
            fathergroupname = self.grouplist[findex]['groupname']
            fathergroupname += ' ' + str(
                self.grouplist[findex]['childcount'] -
                self.grouplist[findex]['childhide']) + '/' + str(
                    self.grouplist[findex]['childcount'])
            parent.setText(0, fathergroupname)

    def dealBeAdded(self, widget):
        reply = QMessageBox.question(
            self, 'Friend add Prompt',
            '%s(%s)Add you as a friend' % (widget.name, widget.id),
            QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if reply == QMessageBox.No:
            self.client.dealRefuseAdded(widget.id)
        else:
            info = ['my good friend', widget.name]
            dialog = Add_Dialog(info)
            for g in self.grouplist:
                dialog.comboBox.addItem(g['groupname'])
            dialog.exec_()

            self.client.dealAcceptAdded(widget.id)
            newitem = QTreeWidgetItem()
            newitem.setSizeHint(0, QSize(self.treeWidget.width(), 55))

            head = widget.data.split('\n'.encode('utf-8'), 1)[1]
            buddy = Buddy(info[1], str(widget.id), head, 0)
            userdic = {
                'user': newitem,
                'username': info[1],
                'userid': widget.id,
                'head': head,
                'ishide': 0
            }

            cindex = self.searchgroup(info[0])
            group = self.grouplist[cindex]['group']
            self.grouplist[cindex]['childcount'] += 1
            self.userslist.append(userdic)
            group.addChild(newitem)
            self.treeWidget.setItemWidget(newitem, 0, buddy)
            self.treeWidget.setCurrentItem(newitem)

            user = {'username': info[1], 'userid': widget.id, 'ishide': 0}
            self.groupInfo[info[0]].append(user)

    def dealFriendOffline(self, id):
        useritemindex = self.searchuser(id)
        if useritemindex is not None:
            self.userslist[useritemindex]['ishide'] = 1
            useritem = self.userslist[useritemindex]['user']
            parent = useritem.parent()
            findex = self.searchgroup(parent)
            widget = self.treeWidget.itemWidget(useritem, 0)
            widget.lblonlinestate.setPixmap(QPixmap('img/bullet-grey.png'))
            self.grouplist[findex]['childishide'] += 1
            fathergroupname = self.grouplist[findex]['groupname']
            fathergroupname += ' ' + str(
                self.grouplist[findex]['childcount'] -
                self.grouplist[findex]['childhide']) + '/' + str(
                    self.grouplist[findex]['childcount'])
            parent.setText(0, fathergroupname)
            self.treeWidget.setCurrentItem(parent)

    def on_bt_adduser_clicked(self):
        des_id = [-1]
        adduser = Dialog_additem(des_id, self.temp, self.userslist,
                                 self.client.id)
        for g in self.grouplist:
            adduser.comboBox.addItem(g['groupname'])
        if adduser.exec_() == 1:
            data = self.client.name.encode('utf-8') + "\n".encode(
                'utf-8') + self.client.head
            protocol = Protocol(len(data), self.client.id, des_id[0],
                                Type.ADD_FRIEND)
            header = protocol.make_packet_header()
            self.client.sock.sendall(header + data)

    def successAddFriend(self, friend, head):
        newitem = QTreeWidgetItem()
        newitem.setSizeHint(0, QSize(self.treeWidget.width(), 55))
        friendName = friend['name']
        friendId = friend['id']
        ishide = friend['ishide']
        buddy = Buddy(friendName, str(friendId), head, ishide)
        userdic = {
            'user': newitem,
            'username': friendName,
            'userid': friendId,
            'head': head,
            'ishide': ishide
        }
        for k, v in self.temp.items():
            if k == friend['id']:
                comboxinfo = self.temp.pop(k)
                break
        cindex = self.searchgroup(comboxinfo)
        group = self.grouplist[cindex]['group']
        groupname = self.grouplist[cindex]['groupname']
        self.grouplist[cindex]['childcount'] += 1
        self.userslist.append(userdic)
        group.addChild(newitem)
        self.treeWidget.setItemWidget(newitem, 0, buddy)
        self.treeWidget.setCurrentItem(newitem)

        user = {'username': friendName, 'userid': friendId, 'ishide': 0}
        self.groupInfo[groupname].append(user)

    def creategroup(self):
        self.groupInfo = groupInfo = self.client.dealInitGroupInfo()
        for groupname in groupInfo.keys():
            hidernum = 0
            group = QTreeWidgetItem(self.treeWidget)
            groupdic = {
                'group': group,
                'groupname': groupname,
                'childcount': 0,
                'childhide': 0
            }
            icon = self.searchIcon(groupname)
            group.setIcon(0, icon)

            for friend in groupInfo[groupname]:
                child = QTreeWidgetItem()
                child.setSizeHint(0, QSize(self.treeWidget.width(), 55))
                friendName = friend['username']
                friendId = friend['userid']
                ishide = friend['ishide']
                head = self.client.dealGetHead(friendId)
                buddy = Buddy(friendName, str(friendId), head, ishide)
                userdic = {
                    'user': child,
                    'username': friendName,
                    'userid': friendId,
                    'head': head,
                    'ishide': ishide
                }
                self.userslist.append(userdic)
                if friend['ishide'] == 1:
                    hidernum += 1
                    userdic['ishide'] = 1
                group.addChild(child)
                self.treeWidget.setItemWidget(child, 0, buddy)

            childnum = group.childCount()
            lastchildnum = childnum - hidernum
            groupdic['childcount'] = childnum
            groupdic['childishide'] = hidernum
            groupname += ' ' + str(lastchildnum) + '/' + str(childnum)
            group.setText(0, groupname)
            group.setExpanded(True)
            self.grouplist.append(groupdic)

    def createusers(self, num):
        randname = "黑子"
        randicon = QIcon(str(num) + '.jpg')
        font = QFont()
        font.setPointSize(16)
        isvip = random.randint(0, 5)
        ishider = random.randint(0, 5)
        if ishider == 1:
            randicon = QIcon(str(num) + 'h.jpg')
        return randname, randicon, font, isvip, ishider

    def searchIcon(self, gpname2):
        if gpname2.find('Friend') >= 0:
            return QIcon('img/buddy.ico')
        elif gpname2.find('同事'):
            return QIcon('img/partner.ico')
        elif gpname2.find('黑名单'):
            return QIcon('img/blacklist.ico')
        else:
            return QIcon('img/defalut.ico')

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            event.accept()

    def mouseMoveEvent(self, QMouseEvent):
        if QMouseEvent.buttons() and Qt.LeftButton:
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False

    def onUsernameChoosed(self, name):
        self.lineEdit.setText(name)

    def on_lineEdit_textChanged(self, text):
        namelist = []
        for itm in self.userslist:
            username = itm['username']
            if username.find(text) >= 0:
                namelist.append(itm['username'])
        self.m_model.removeRows(0, self.m_model.rowCount())

        for i in range(0, len(namelist)):
            self.m_model.insertRow(0)
            self.m_model.setData(self.m_model.index(0, 0), namelist[i])

    def on_bt_search_clicked(self):
        username = self.lineEdit.text()
        if len(username) > 0:
            useritemindex = self.searchuser(username)
            if useritemindex is not None:
                useritem = self.userslist[useritemindex]['user']
                self.treeWidget.setCurrentItem(useritem)
            else:
                QMessageBox.information(self, 'Message',
                                        'This friend does not exist!')

    def closeEvent(self, event):
        reply = QMessageBox.question(
            self, 'Prompt', 'Are you sure you want to quit the program?',
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.No:
            event.ignore()
        else:
            self.hide()
            self.client.dealUpdate(self.groupInfo)
            self.closeWindow()
            time.sleep(3)
            self.client.dealQuit()
            time.sleep(1)
            self.listener.terminate()
            event.accept()

    def msgCache(self):
        self.cache.show()

    def setUp(self):
        setup = SetInfoDialog(self.client)
        if setup.exec_() > 0:
            self.lblName.setText(
                self.client.name
            )  ################################################################################需要设置头像!!!!!!!
            image = QImage()
            image.loadFromData(self.client.head)
            self.lblHead.setPixmap(QPixmap.fromImage(image))
            self.client.dealSetHead()
            self.client.dealSetName()

    def delGroup(self):
        hititem = self.groups.currentItem()
        group = self.groups.itemWidget(hititem)
        gid = int(group.id.text())
        self.client.dealDeleteGroup(gid)
        row = self.groups.row(hititem)
        self.groups.takeItem(row)

    def contextMenuEvent(self, event):
        x = QCursor.pos().x()
        y = QCursor.pos().y()
        widget = QApplication.widgetAt(x, y)
        if type(widget) == Group:
            menu = QMenu(self)
            pDeleteAct = QAction('Delete group', self.groups)
            menu.addAction(pDeleteAct)
            pDeleteAct.triggered.connect(self.delGroup)
            menu.popup(self.mapToGlobal(event.pos()))
        elif type(widget) == QWidget:
            hititem = self.treeWidget.currentItem()
            pgroupmenu = QMenu(self)
            pAddgroupAct = QAction('Add group', self.treeWidget)
            pRenameAct = QAction('Rename', self.treeWidget)
            pDeleteAct = QAction('Delete group', self.treeWidget)
            pgroupmenu.addAction(pAddgroupAct)
            pgroupmenu.addAction(pRenameAct)
            pgroupmenu.addAction(pDeleteAct)
            pAddgroupAct.triggered.connect(self.addgroup)
            pRenameAct.triggered.connect(self.renamegroup)
            if self.treeWidget.itemAbove(hititem) is None:
                pDeleteAct.setEnabled(False)
            else:
                pDeleteAct.setEnabled(True)
                pDeleteAct.triggered.connect(self.deletegroup)
            pgroupmenu.popup(self.mapToGlobal(event.pos()))

        elif type(widget) == Buddy:
            hititem = self.treeWidget.currentItem()
            root = hititem.parent()
            if root.childCount() > 0:
                pItemmenu = QMenu(self)
                pDeleteItemAct = QAction('Delete contact', pItemmenu)
                pItemmenu.addAction(pDeleteItemAct)
                pDeleteItemAct.triggered.connect(self.delete)
                if len(self.grouplist) > 1:
                    pSubMenu = QMenu('Transfer contacts to', pItemmenu)
                    pItemmenu.addMenu(pSubMenu)
                    for item_dic in self.grouplist:
                        if item_dic['group'] is not root:
                            pMoveAct = QAction(item_dic['groupname'],
                                               pItemmenu)
                            pSubMenu.addAction(pMoveAct)
                            pMoveAct.triggered.connect(self.moveItem)
                if len(self.getListitems(self.menuflag)) == 1:
                    pRenameItemAct = QAction('Setting note', pItemmenu)
                    pItemmenu.addAction(pRenameItemAct)
                    pRenameItemAct.triggered.connect(self.renameItem)
                if self.menuflag > 0 and root.childCount() > 1:
                    pBatchAct = QAction('Batch operation within a group',
                                        pItemmenu)
                    pItemmenu.addAction(pBatchAct)
                    pBatchAct.triggered.connect(self.Batchoperation)
                elif self.menuflag < 0:
                    pCancelBatchAct = QAction('Cancel batch operation',
                                              pItemmenu)
                    pItemmenu.addAction(pCancelBatchAct)
                    pCancelBatchAct.triggered.connect(
                        self.CancelBatchoperation)

                pItemmenu.popup(self.mapToGlobal(event.pos()))

    def moveItem(self):
        movelist = self.getListitems(self.menuflag)
        togroupname = self.sender().text()
        mindex = self.searchgroup(togroupname)
        togroup = self.grouplist[mindex]['group']
        self.deleteItems(movelist, flag=0)
        self.add(togroup, movelist)
        self.tmpuseritem.clear()

    def delete(self):
        delitems = self.getListitems(self.menuflag)
        self.deleteItems(delitems)
        self.tmpuseritem.clear()

    def deleteItems(self, items, flag=1):
        for delitem in items:
            delitem.setData(0, Qt.CheckStateRole, QVariant())
            pindex = delitem.parent().indexOfChild(delitem)
            dindex = self.searchuser(delitem)
            ishide = self.userslist[dindex]['ishide']
            id = self.userslist[dindex]['userid']
            if flag == 1:
                self.client.dealDelFriend(id)
                del self.userslist[dindex]

            fathergroup = delitem.parent()
            findex = self.searchgroup(fathergroup)
            parentName = self.grouplist[findex]['groupname']
            for user in self.groupInfo[parentName]:
                if user['userid'] == id:
                    self.groupInfo[parentName].remove(user)
                    break

            fathergroup = delitem.parent()
            findex = self.searchgroup(fathergroup)
            if ishide == 1:
                self.grouplist[findex]['childishide'] -= 1
                self.grouplist[findex]['childcount'] -= 1
            else:
                self.grouplist[findex]['childcount'] -= 1

            delitem.parent().takeChild(pindex)

    def add(self, group, items):
        gindex = self.searchgroup(group)
        gname = self.grouplist[gindex]['groupname']
        for item in items:
            aindex = self.searchuser(item)
            ishide = self.userslist[aindex]['ishide']
            userid = self.userslist[aindex]['userid']
            username = self.userslist[aindex]['username']
            head = self.userslist[aindex]['head']
            if ishide == 1:
                self.grouplist[gindex]['childishide'] += 1
                self.grouplist[gindex]['childcount'] += 1
            else:
                self.grouplist[gindex]['childcount'] += 1
            buddy = Buddy(username, str(userid), head, ishide)

            group.addChild(item)
            self.treeWidget.setItemWidget(item, 0, buddy)
            self.treeWidget.itemWidget(item, 0).show()
            self.treeWidget.setCurrentItem(item)

            user = {'username': username, 'userid': userid, 'ishide': 0}
            self.groupInfo[gname].append(user)

    def Batchoperation(self):
        self.menuflag *= -1
        group = self.getListitems()[0].parent()
        childnum = group.childCount()
        for c in range(childnum):
            child = group.child(c)
            child.setCheckState(0, Qt.Unchecked)

    def CancelBatchoperation(self):
        self.menuflag *= -1
        group = self.getListitems()[0].parent()
        childnum = group.childCount()
        for c in range(childnum):
            child = group.child(c)
            child.setData(0, Qt.CheckStateRole, QVariant())

    def isclick(self, item):
        if item.checkState(0) == Qt.Checked:
            if self.tmpuseritem.count(item) == 0:
                self.tmpuseritem.append(item)
        else:
            if len(self.tmpuseritem) > 0:
                if self.tmpuseritem.count(item) != 0:
                    i = self.tmpuseritem.index(item)
                    del self.tmpuseritem[i]

    def renameItem(self):
        hituser = self.treeWidget.currentItem()
        widget = self.treeWidget.itemWidget(hituser, 0)
        uindex = self.searchuser(hituser)
        unewname, ok = QInputDialog.getText(self, 'Prompt Information',
                                            'Please enter a note name')
        if ok:
            if len(unewname) == 0:
                QMessageBox.information(self, 'Prompt',
                                        'Note name cannot be empty')
            else:
                widget.name.setText(unewname)
                self.userslist[uindex]['username'] = unewname
                id = self.userslist[uindex]['userid']
                parent = hituser.parent()
                parentIndex = self.searchgroup(parent)
                parentName = self.grouplist[parentIndex]['groupname']
                for user in self.groupInfo[parentName]:
                    if user['userid'] == id:
                        user['username'] = unewname

    def searchuser(self, hituser):
        if isinstance(hituser, str):
            if hituser.isdigit():
                for i, u in enumerate(self.userslist):
                    if str(u['userid']) == hituser:
                        return i
            else:
                for i, u in enumerate(self.userslist):
                    if u['username'] == hituser:
                        return i
        elif isinstance(hituser, int):
            for i, u in enumerate(self.userslist):
                if u['userid'] == hituser:
                    return i
        else:
            for i, u in enumerate(self.userslist):
                if hituser == u['user']:
                    return i
        return None

    def getListitems(self, flag=1):
        if flag > 0:
            return self.treeWidget.selectedItems()
        else:
            return self.tmpuseritem

    def addgroup(self):
        gname, ok = QInputDialog.getText(self, 'Prompt Information',
                                         'Please enter a group name')
        if ok:
            if len(gname) == 0:
                QMessageBox.information(self, 'Prompt',
                                        'Group name cannot be empty')
            else:
                hidernum = 0
                group = QTreeWidgetItem(self.treeWidget)
                groupdic = {
                    'group': group,
                    'groupname': gname,
                    'childcount': 0,
                    'childhide': 0
                }
                #sself.groupInfo[gname] = ''
                icon = self.searchIcon(gname)
                group.setIcon(0, icon)
                childnum = group.childCount()
                lastchildnum = childnum - hidernum
                groupdic['childcount'] = childnum
                groupdic['childishide'] = hidernum
                self.groupInfo[gname] = []
                gname += ' ' + str(lastchildnum) + '/' + str(childnum)
                group.setText(0, gname)
                self.grouplist.append(groupdic)

    def renamegroup(self):
        hitgroup = self.treeWidget.currentItem()
        gnewname, ok = QInputDialog.getText(self, 'Prompt',
                                            'Please enter a new group name')
        if ok:
            if len(gnewname) == 0:
                QMessageBox.information(self, 'Prompt',
                                        'Group name cannot be empty')
            else:
                hitgroup.setText(0, gnewname)
                newicon = self.searchIcon(hitgroup.text(0))
                hitgroup.setIcon(0, newicon)
                gindex = self.searchgroup(hitgroup)
                oldname = self.grouplist[gindex]['groupname']
                self.grouplist[gindex]['groupname'] = gnewname
                self.treeWidget.setCurrentItem(hitgroup.child(0))
                self.groupInfo[gnewname] = self.groupInfo.pop(oldname)

    def deletegroup(self):
        hitgroup = self.treeWidget.currentItem()
        gindex = self.searchgroup(hitgroup)
        reply = QMessageBox.question(
            self, 'Warning', 'Are you sure you want to delete this group?',
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.treeWidget.takeTopLevelItem(gindex)
            groupname = self.grouplist[gindex]['groupname']
            del self.grouplist[gindex]
            del self.groupInfo[groupname]

    def searchgroup(self, hitgroup):
        if isinstance(hitgroup, str):
            for i, g in enumerate(self.grouplist):
                if g['groupname'] == hitgroup:
                    return i
        else:
            for i, g in enumerate(self.grouplist):
                if g['group'] == hitgroup:
                    return i

    def restatistic(self, item, preitem):
        if item:
            fathergroup = item.parent()
            if fathergroup:
                self.restatistic_op(fathergroup)
            else:
                self.restatistic_op(item)
        elif preitem.parent().childCount() == 1:
            lastgroupname = preitem.parent().text(0).split()[0] + ' 0/0'
            preitem.parent().setText(0, lastgroupname)
            self.menuflag = 1

    def restatistic_op(self, itemorgroup):
        gindex = self.searchgroup(itemorgroup)
        totalcount = self.grouplist[gindex]['childcount']
        hidecount = self.grouplist[gindex]['childishide']
        fathergroupname = self.grouplist[gindex]['groupname']
        fathergroupname += ' ' + str(totalcount -
                                     hidecount) + '/' + str(totalcount)
        itemorgroup.setText(0, fathergroupname)