示例#1
0
def connectDatabase(envt):
	"""Connect base MySQL/Sqlite."""
	FILE__INI = 'DBAlbums.json'
	Json_params = JsonParams(FILE__INI)
	group_envt = Json_params.getMember(envt)
	MODE_SQLI = group_envt['typb']
	BASE_RAC = r'' + group_envt['raci']
	RACI_DOU = group_envt['cate']
	boolcon = False
	if MODE_SQLI == 'sqlite':
		db = QSqlDatabase.addDatabase("QSQLITE")
		db.setDatabaseName(BASE_SQLI.format(envt=envt))
		if not db.isValid():
			qDebug(envt+' problem no valid database')
	else:
		BASE_SEV = group_envt['serv']
		BASE_USR = group_envt['user']
		BASE_PAS = group_envt['pass']
		BASE_NAM = group_envt['base']
		BASE_PRT = group_envt['port']
		if MODE_SQLI == 'mysql':
			db = QSqlDatabase.addDatabase("QMYSQL")
			db.setHostName(BASE_SEV)
			db.setDatabaseName(BASE_NAM)
			db.setUserName(BASE_USR)
			db.setPassword(BASE_PAS)
			db.setPort(BASE_PRT)
		elif MODE_SQLI == 'mssql':
			db = QSqlDatabase.addDatabase("QODBC3")
			driver = "DRIVER={SQL Server Native Client 11.0};Server=" + BASE_SEV + ";Database=" + BASE_NAM
			driver += ";Uid=" + BASE_USR + ";Port=" + str(BASE_PRT) + ";Pwd=" + BASE_PAS + ";Trusted_connection=yes"
			#print(driver)
			db.setDatabaseName(driver);
	list_category = []
	if RACI_DOU is not None:
		list_category += Json_params.buildCategories(envt)
	if db.isValid():
		boolcon = db.open()
	else:
		qDebug(envt+' problem for open database : '+db.lastError().text())
	return boolcon, db, MODE_SQLI, BASE_RAC, list_category
示例#2
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from os import path
from PyQt5.QtCore import Qt, QVariant, QModelIndex, pyqtSignal, QSortFilterProxyModel, QAbstractTableModel
from PyQt5.QtSql import QSqlQuery
from PyQt5.QtGui import QColor
from DBDatabase import DBFuncBase, getrequest
from DBFunction import convertUNC
from DBReadJson import JsonParams

FILE__INI = 'DBAlbums.json'
Json_params = JsonParams(FILE__INI)
group_dbalbums = Json_params.getMember('dbalbums')
TEXT_NCO = group_dbalbums['text_nocov']
THUN_NOD = group_dbalbums['thnail_nod']
FONT_MAI = group_dbalbums['font00_ttx']


# MODEL ABSTRACT generique
class ModelDBAbstract(QAbstractTableModel):
    """Abstract model for qtableview."""
    signalthubuild = pyqtSignal(float, str)  # build base

    def __init__(self, parent, colsname, req):
        """Init Model Abstract."""
        super(ModelDBAbstract, self).__init__(parent)
        self.parent = parent
        self.columns = colsname
        self.request = req
        self.arraydata = []
示例#3
0
class InventGui(QWidget, Ui_UpdateWindows):
    signalend = pyqtSignal()

    PATH_PROG = path.dirname(path.abspath(__file__))
    LOGS_PROG = path.join(PATH_PROG, 'LOG')
    # Read File DBAlbums.ini
    qDebug('read json params file')
    FILE__INI = 'DBAlbums.json'
    Json_params = JsonParams(FILE__INI)

    group_dbalbums = Json_params.getMember('dbalbums')
    VERS_PROG = group_dbalbums['prog_build']
    TITL_PROG = "DBAlbums v{v} (2017)".format(v=VERS_PROG)
    TITL_PROG = TITL_PROG + " : Update Database"
    WIDT_MAIN = group_dbalbums['wgui_width']
    HEIG_MAIN = group_dbalbums['wgui_heigh']
    WIDT_PICM = group_dbalbums['thun_csize']
    WINS_ICO = path.join(PATH_PROG, 'IMG', group_dbalbums['wins_icone'])
    THEM_COL = group_dbalbums['name_theme']
    TEXT_NCO = group_dbalbums['text_nocov']
    FONT_CON = group_dbalbums['font01_ttx']

    def __init__(self,
                 list_albums,
                 list_columns,
                 list_category,
                 typeupdate,
                 modsql,
                 envt,
                 themecolor,
                 parent=None):
        """Init Gui, start invent"""
        super(InventGui, self).__init__(parent)
        self.setupUi(self)
        self.resize(self.WIDT_MAIN, self.HEIG_MAIN - 300)
        self.setWindowIcon(QIcon(self.WINS_ICO))
        self.setWindowTitle(self.TITL_PROG + " Environment : " + envt +
                            " mode : " + typeupdate)
        centerWidget(self)

        self.parent = parent
        self.list_albums = list_albums
        self.list_category = list_category
        self.list_columns = list_columns
        self.modsql = modsql
        self.envits = envt
        self.typeupdate = typeupdate
        self.curthe = themecolor
        self.logname = QDateTime.currentDateTime().toString(
            'yyMMddhhmmss') + "_UPDATE_DATABASE_" + self.envits + ".log"
        self.logname = path.join(self.LOGS_PROG, self.logname)
        self.total_p = None
        self.albumnew = 0
        self.alupdate = 0
        self.aldelete = 0
        self.apresent = 0
        self.actionerror = 0
        self.selecttrowg = 0
        self.list_actions = []

        font = QFont()
        font.setFamily("Courrier New")
        font.setFixedPitch(True)
        font.setPointSize(10)
        fontconsol = QFont()
        fontconsol.setFamily(self.FONT_CON)
        fontconsol.setFixedPitch(True)
        fontconsol.setPointSize(8)
        self.levelcolors = [Qt.white, Qt.green, Qt.magenta, Qt.red]

        self.menua = QMenu()
        self.action_OPF = self.menua.addAction(
            self.style().standardIcon(QStyle.SP_DialogOpenButton),
            "Open Folder...", self.getFolder)

        self.lab_result.setFont(font)
        self.lab_release.setFont(font)
        self.lab_advance.setFont(font)
        self.lab_releaseadvance.setFont(font)

        self.textEditrelease.setStyleSheet(
            "background-color: black;color:white;")
        self.textEditrelease.setLineWrapMode(QTextEdit.NoWrap)
        self.textEditrelease.setReadOnly(True)
        self.textEditrelease.setFont(fontconsol)
        self.vScrollBar = QScrollBar(self.textEditrelease.verticalScrollBar())
        self.vScrollBar.sliderPressed.connect(self.onScrollPressed)

        self.btn_action.clicked.connect(self.realiseActions)
        self.btn_action.setEnabled(False)
        self.btn_quit.clicked.connect(self.closeImport)
        self.lcdTime.setSegmentStyle(QLCDNumber.Flat)

        self.seconds = 0
        self.myThreadtime = myThreadTimer(self)
        self.myThreadtime.timeElapsed.connect(self.showlcd)
        self.myThreadtime.start()

        self.tbl_update.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tbl_update.customContextMenuRequested.connect(
            self.popUpTreeUpdate)
        self.tableMdlUpd = ModelTableUpdatesABS(self, [[] * 5])
        self.tbl_update.setModel(self.tableMdlUpd)
        for i in range(len(self.tableMdlUpd.U_C_WIDTH)):
            self.tbl_update.setColumnWidth(i, self.tableMdlUpd.U_C_WIDTH[i])
        self.tbl_update.verticalHeader().setDefaultSectionSize(
            self.tableMdlUpd.C_HEIGHT)
        self.tbl_update.horizontalHeader().setStretchLastSection(True)

        self.applyTheme()
        self.show()

    def startAnalyse(self):
        qDebug('Start BuildInvent')
        self.setCursor(Qt.WaitCursor)
        self.prepareInvent = BuildInvent(self.list_albums, self.list_columns,
                                         self.list_category, self.typeupdate,
                                         self.modsql, self.envits)
        self.prepareInvent.signalchgt.connect(self.onBuild)
        self.prepareInvent.signaltext.connect(self.updateInfos)
        self.prepareInvent.inventDatabase()
        self.setCursor(Qt.ArrowCursor)
        self.lab_result.setText('Completed Analyse in ' + self.total_p)
        qDebug('End BuildInvent')

        self.btn_quit.setText('Close')
        if len(self.prepareInvent.list_action
               ) > 0 and not self.checkBoxStart.isChecked():
            self.btn_action.setEnabled(True)
        self.realiseActions()

    def onBuild(self, percent, message):
        """Display advance browsing folders."""
        self.lab_result.setText(message)
        self.progressBar.setValue(percent)
        mesresu = 'PRESENT : ' + format(
            self.prepareInvent.apresent + self.prepareInvent.alupdate -
            self.prepareInvent.aldelete, '05d')
        mesresu += '\nADD     : ' + format(self.prepareInvent.albumnew, '05d')
        mesresu += '\nUPDATE  : ' + format(self.prepareInvent.alupdate, '05d')
        mesresu += '\nDELETE  : ' + format(self.prepareInvent.aldelete, '05d')
        self.lab_advance.setText(mesresu)
        self.lab_releaseadvance.setText(mesresu)
        self.tableMdlUpd.update(self.prepareInvent.list_action)
        self.tbl_update.scrollToBottom()
        QApplication.processEvents()

    def realiseActions(self, list_actions=None):
        """Execute Actions Update."""
        if list_actions is None:
            self.list_actions = self.prepareInvent.list_action
            self.apresent = self.prepareInvent.apresent
            self.albumnew = self.prepareInvent.albumnew
            self.alupdate = self.prepareInvent.alupdate
            self.aldelete = self.prepareInvent.aldelete
        else:
            # no analyse
            self.btn_quit.setText('Close')
            self.list_actions = list_actions
            self.lab_result.setText('No Analyse')
            self.lab_advance.setText('')
            self.progressBar.setValue(100)
            self.tableMdlUpd.update(self.list_actions)
            self.apresent = len(self.list_albums)
            for action in self.list_actions:
                if action[2] == 'DELETE':
                    self.aldelete += 1
                elif action[2] == 'UPDATE':
                    self.alupdate += 1
                elif action[2] == 'ADD':
                    self.albumnew += 1
        run = ReleaseInvent(self.list_actions, self.modsql)
        run.signalrun.connect(self.updateRun)
        run.signalend.connect(self.updateEnd)
        run.signaltxt.connect(self.updateInfos)
        run.executeActions()

    def updateRun(self, percent, text):
        """Display run operations update database."""
        index = self.tableMdlUpd.index(self.selecttrowg, 0)
        self.tbl_update.selectRow(index.row())
        index = self.tbl_update.currentIndex()
        self.tbl_update.scrollTo(index)
        self.selecttrowg += 1
        self.progressBarrelease.setValue(percent)
        if text == 'DELETE':
            self.aldelete -= 1
            self.apresent -= 1
        elif text == 'UPDATE':
            self.alupdate -= 1
        elif text == 'ADD':
            self.albumnew -= 1
            self.apresent += 1
        elif text == 'ERROR':
            self.actionerror += 1
        mesresu = 'ERROR   : ' + format(self.actionerror, '05d')
        mesresu += '\nADD     : ' + format(self.albumnew, '05d')
        mesresu += '\nUPDATE  : ' + format(self.alupdate, '05d')
        mesresu += '\nDELETE  : ' + format(self.aldelete, '05d')
        self.lab_releaseadvance.setText(mesresu)
        QApplication.processEvents()

    @pyqtSlot()
    def updateEnd(self):
        """Operations finished."""
        QApplication.processEvents()
        self.lab_release.setText('Completed Operations in ' + self.total_p)
        if len(self.list_actions) > 0:
            # create log file
            self.textEditrelease.append('\n- Completed Operations in ' +
                                        self.total_p)
            self.textEditrelease.append('\n- Create log file : ' +
                                        self.logname)
            text_file = open(self.logname, "w", 'utf-8')
            text_file.write(self.textEditrelease.toPlainText())
            text_file.close()
            self.textEditrelease.moveCursor(QTextCursor.Start)
            self.textEditrelease.ensureCursorVisible()
            # refresh
            self.signalend.emit()
            QMessageBox.information(self, 'Update Database',
                                    'Completed Operations in ' + self.total_p)

    def updateInfos(self, line, level=None):
        """Write Reception signal run update."""
        if not level:
            if line.startswith('-'):
                level = 1
            elif line.startswith('WARNING'):
                level = 2
            elif line.startswith('ERROR'):
                level = 3
            else:
                level = 0
        # set color
        self.textEditrelease.setTextColor(QColor(self.levelcolors[level]))
        if self.focusWidget() != self.vScrollBar:
            # display
            cursor = self.textEditrelease.textCursor()
            cursor.movePosition(QTextCursor.End)
        #cursor.insertText(line)
        self.textEditrelease.append(line.rstrip())
        self.textEditrelease.setTextCursor(cursor)
        if self.focusWidget() != self.vScrollBar:
            self.textEditrelease.ensureCursorVisible()
        self.textEditrelease.horizontalScrollBar().setValue(0)

    def golbalInsertCovers(self):
        request = "SELECT ALBUMS.ID_CD, ALBUMS.Cover FROM ALBUMS " \
           "LEFT JOIN COVERS ON ALBUMS.ID_CD = COVERS.ID_CD " \
           "WHERE COVERS.ID_CD IS NULL AND ALBUMS.Cover<>'{textnopic}'"
        request = request.format(textnopic=self.TEXT_NCO)
        query = QSqlQuery(request)
        query.exec_()
        while query.next():
            DBFuncBase().imageToSql(query.value(1), query.value(0),
                                    self.WIDT_PICM)

    def getFolder(self):
        """Open album folder."""
        indexes = self.tbl_update.selectedIndexes()
        self.currow = indexes[0].row()
        albumpath = self.tableMdlUpd._array[self.currow][5]
        openFolder(albumpath)

    def popUpTreeUpdate(self, position):
        self.menua.exec_(self.tbl_update.viewport().mapToGlobal(position))

    @pyqtSlot(int)
    def showlcd(self, seconds):
        hours, seconds = seconds // 3600, seconds % 3600
        minutes, seconds = seconds // 60, seconds % 60
        self.total_p = "%02d:%02d:%02d" % (hours, minutes, seconds)
        self.lcdTime.display(self.total_p)
        QApplication.processEvents()

    def applyTheme(self):
        """Apply color Theme to main Gui."""
        # main
        mainstyle = 'QWidget{{background-color: {col1};}}' \
           'QLCDNumber{{border: none;color: black; background-color: {col1};}}' \
           'QScrollBar:vertical{{width: 14px;}}' \
           'QScrollBar:horizontal{{height: 14px;}}' \
           'QTableView::item:selected{{ background-color:{col5}; color:white;}}'
        mainstyle = mainstyle.format(col1=self.curthe.listcolors[0],
                                     col2=self.curthe.listcolors[1],
                                     col5=self.curthe.listcolors[4])
        self.setStyleSheet(mainstyle)
        gridstyle = 'alternate-background-color: {col3};background-color: {col4};'
        gridstyle = gridstyle.format(col3=self.curthe.listcolors[2],
                                     col4=self.curthe.listcolors[3])
        self.tbl_update.setStyleSheet(gridstyle)

    def closeImport(self):
        """Close Windows."""
        self.myThreadtime.quit()
        self.myThreadtime.stop()
        self.destroy()

    def onScrollPressed(self):
        pass
示例#4
0
class CardAlbum(QObject):
    signaltxt = pyqtSignal(str, int)  # message / level display

    mask_artwork = ('.jpg', '.jpeg', '.png', '.bmp', '.tif', '.bmp', '.tiff')
    mask_acovers = ('cover.jpg', 'Cover.jpg', 'cover.jpeg', 'cover.png',
                    'front.jpg', 'folder.jpg', 'folder.jpeg')
    mask_amedias = ('.flac', '.ape', '.wma', '.mp3', '.wv', '.aac', '.mpc')
    DCardAlbum = {
        'ID_CD': None,  # Base
        'CATEGORY': None,  # Params
        'FAMILY': None,  # Params
        'NAME': None,  # Path
        'ARTIST': None,  # Tag
        'PATHNAME': None,  # Path
        'POSITION': None,  # Path
        'SUBPOSITION': None,  # Path
        'POSITIONHDD': None,  # Path
        'AUDIOTRACKS': 0,  # Files
        'TRACKS': 0,  # Files
        'CUE': 0,  # Files
        'COVER': None,  # Files / Tag
        'PIC': 0,  # Files
        'SIZE': 0,  # Files
        'CD': 0,  # Tag / Path / Files
        'YEAR': None,  # Path / Tag
        'ISRC': None,  # Path
        'LABEL': None,  # Path
        'TAGISRC': None,  # Tag
        'TAGLABEL': None,  # Tag
        'STYLE': None,  # Tag
        'COUNTRY': None,  # Tag
        'LENGTHSECONDS': 0,  # Tag
        'LENGTHDISPLAY': None,  # Tag / Calcul
        'TYPEMEDIA': None,  # Tag
        'SCORE': 0,  # default value
        'TAGMETHOD': None,  # method tag album
        'ADD': None,  # Calcul
        'MODIFIED': None  # Calcul
    }
    PATH_PROG = path.dirname(path.abspath(__file__))
    # Read File DBAlbums.ini
    FILE__INI = 'DBAlbums.json'
    Json_params = JsonParams(FILE__INI)
    group_dbalbums = Json_params.getMember('dbalbums')
    TEXT_NCO = group_dbalbums['text_nocov']

    def __init__(self, parent=None):
        """Init."""
        super(CardAlbum, self).__init__(parent)
        self.parent = parent

    def defineAlbum(self, pathalbum, category, family):
        """Define Card Album."""
        cardalbum = deepcopy(self.DCardAlbum)
        listcardtrack = []
        cardalbum['NAME'] = path.basename(pathalbum).replace('_', ' ').replace(
            '-WEB', '')
        list_tracksaudio = list(getListFiles(pathalbum, self.mask_amedias))
        cardalbum['AUDIOTRACKS'] = len(list_tracksaudio)
        if cardalbum['AUDIOTRACKS'] > 0:
            cardalbum['CATEGORY'] = category
            cardalbum['FAMILY'] = family
            cardalbum['PATHNAME'] = pathalbum
            cardalbum['PIC'] = len(
                list(getListFiles(pathalbum, self.mask_artwork)))
            cardalbum['SIZE'] = int(
                round(getFolderSize(pathalbum) / 1024 / 1024, 0))
            cardalbum['POSITION'] = pathalbum.split("\\")[-3]
            cardalbum['SUBPOSITION'] = pathalbum.split("\\")[-2]
            cardalbum['POSITIONHDD'] = pathalbum.split(
                "\\")[-3] + '\\' + pathalbum.split("\\")[-2]

            # cover path
            coversfile = list(
                getListFilesNoSubFolders(pathalbum, self.mask_acovers,
                                         'Exactly'))
            coversfile.sort()
            if len(coversfile) > 0:
                # get first
                cardalbum['COVER'] = coversfile[0]
            else:
                coversfile = list(
                    getListFiles(pathalbum, self.mask_acovers, 'Exactly'))
                coversfile.sort()
                if len(coversfile) > 0:
                    cardalbum['COVER'] = coversfile[0]
                else:
                    # tag no picture
                    cardalbum['COVER'] = self.TEXT_NCO

            # year path
            yearfind = match(r'.*([(][1-2][0-9]{3}[)])', cardalbum['NAME'])
            if yearfind:
                cardalbum['YEAR'] = yearfind.group(1)[1:-1]
                cardalbum['NAME'] = cardalbum['NAME'][:-6]

            # label path
            if 'LABEL' in family.upper():
                cardalbum['LABEL'] = cardalbum['SUBPOSITION'].upper()
                # isrc path
                if cardalbum['NAME'].startswith('['):
                    cardalbum['ISRC'] = cardalbum['NAME'].split(']')[0].split(
                        '[')[1]
                    cardalbum['NAME'] = cardalbum['NAME'][cardalbum['NAME'].
                                                          find(']') + 2:]

            # artist path
            if 'ARTIST' in family.upper():
                cardalbum['ARTIST'] = cardalbum['SUBPOSITION'].upper()

            # list valid CUEsheet file
            listfilescue = []
            filescue = list(getListFiles(pathalbum, ('.cue', )))
            for filecue in filescue:
                try:
                    parser = CueParser(filecue)
                    lastfile = parser.lastfiletrack
                    pathmedia = path.join(path.dirname(filecue), lastfile)
                    if pathmedia.upper().endswith('.WAV'):
                        pathmedia = pathmedia[:-3] + list_tracksaudio[0].split(
                            '.')[-1]
                    if path.exists(pathmedia):
                        listfilescue.append(filecue)
                except:
                    pass
            cardalbum['CUE'] = len(listfilescue)
            listfilescue.sort(reverse=False)

            # TAG file media method ? CUE or TAG
            if len(listfilescue) < cardalbum['AUDIOTRACKS']:
                cardalbum['TAGMETHOD'] = 'TAG'
                # album folder numbers of CD ?
                audioroot = list(
                    getListFilesNoSubFolders(pathalbum, self.mask_amedias))
                if len(audioroot) > 0:
                    cardalbum['CD'] += 1
                    albumcardtracks = CardTracks().defineListTracksFiles(
                        pathalbum)
                    for cardtrack in albumcardtracks:
                        if cardtrack['TRACKNUMBER'] is not None:
                            cardtrack['TRACKORDER'] = str(
                                cardtrack['TRACKNUMBER'].split('/')[0]).zfill(
                                    2)
                    listcardtrack += albumcardtracks
                elif len(audioroot) < cardalbum['AUDIOTRACKS']:
                    albumfolders = getListFolders(pathalbum)
                    albumfolders.sort(reverse=False)
                    for albumfolder in albumfolders:
                        fullalbumfolder = path.join(pathalbum, albumfolder)
                        if len(
                                list(
                                    getListFilesNoSubFolders(
                                        fullalbumfolder,
                                        self.mask_amedias))) > 0:
                            cardalbum['CD'] += 1
                            albumcardtracks = CardTracks(
                            ).defineListTracksFiles(fullalbumfolder)
                            counter = 1
                            for cardtrack in albumcardtracks:
                                cardtrack['DISC'] = cardalbum['CD']
                                if cardtrack['TRACKNUMBER'] is None:
                                    cardtrack['TRACKORDER'] = str(
                                        cardalbum['CD']).zfill(2) + str(
                                            counter).zfill(2)
                                else:
                                    cardtrack['TRACKORDER'] = str(
                                        cardalbum['CD']).zfill(2) + str(
                                            cardtrack['TRACKNUMBER'].split(
                                                '/')[0]).zfill(2)
                                counter += 1
                            listcardtrack += albumcardtracks

            else:
                cardalbum['TAGMETHOD'] = 'CUE'
                for filecue in listfilescue:
                    cardalbum['CD'] = cardalbum['CD'] + 1
                    albumcardtracks = CardTracks().defineListTracksCUE(
                        filecue, list_tracksaudio[0].split('.')[-1])
                    for cardtrack in albumcardtracks:
                        cardtrack['DISC'] = cardalbum['CD']
                        if len(listfilescue) > 1:
                            cardtrack['TRACKORDER'] = str(
                                cardalbum['CD']).zfill(2) + str(
                                    cardtrack['TRACKNUMBER']).zfill(2)
                        else:
                            cardtrack['TRACKORDER'] = str(
                                cardtrack['TRACKNUMBER']).zfill(2)
                        if cardtrack['FILENAME'].upper().endswith('.WAV'):
                            cardtrack['FILENAME'] = cardtrack[
                                'FILENAME'][:-3] + cardtrack[
                                    'TYPEMEDIA'].split('/')[1]
                    listcardtrack += albumcardtracks

            # numbers cds path
            if cardalbum['CD'] is None:
                numbercdfind = match(r'.*([1-9][C][D])', cardalbum['NAME'])
                if numbercdfind:
                    cardalbum['CD'] = numbercdfind.group(1)[:-2]

            # tracks tag to album card
            if listcardtrack:
                cardtrack = listcardtrack[0]
                cardalbum['COUNTRY'] = cardtrack['COUNTRY']
                cardalbum['TYPEMEDIA'] = cardtrack['TYPEMEDIA']
                if cardtrack['ISRC'] is not None:
                    cardalbum['TAGISRC'] = cardtrack['ISRC'].upper()
                if cardtrack['ORGANIZATION'] is not None:
                    cardalbum['TAGLABEL'] = cardtrack['ORGANIZATION'].upper()
                if cardalbum['TAGISRC'] is None:
                    pass
                    #cardalbum['TAGISRC'] = cardalbum['ISRC']

                # albumartist or artist tag
                if ' VA ' in cardalbum['NAME'] or cardalbum['NAME'].startswith(
                        'VA '):
                    cardalbum['ARTIST'] = 'Various'
                else:
                    cardalbum['ARTIST'] = cardtrack['ALBUMARTIST']
                    if cardalbum['ARTIST'] is not None:
                        cardalbum['ARTIST'] = cardalbum['ARTIST'].replace(
                            'VA', 'Various')
                        cardalbum['ARTIST'] = cardalbum['ARTIST'].replace(
                            'Various Artists', 'Various')
                    if cardalbum['ARTIST'] is None:
                        cardalbum['ARTIST'] = cardtrack['ARTIST']

                # year tag
                if cardalbum['YEAR'] is None:
                    cardalbum['YEAR'] = cardtrack['DATE']
                else:
                    if cardtrack['DATE'] is not None:
                        if cardalbum['YEAR'] != cardtrack['DATE'][:4]:
                            self.signaltxt.emit(
                                'WARNING : year tag {tag} <> year path {pat}'.
                                format(tag=cardtrack['DATE'],
                                       pat=cardalbum['YEAR'][:4]), 2)
            else:
                self.signaltxt.emit('ERROR : no tracks ' + pathalbum, 3)

            # no year tag and no year path format
            if cardalbum['YEAR'] is None:
                yearfind = match(r'.*([1-2][0-9]{3})', cardalbum['NAME'])
                if yearfind:
                    cardalbum['YEAR'] = yearfind.group(1)

            # cover if one image artwork
            if cardalbum['COVER'] == self.TEXT_NCO and cardalbum['PIC'] == 1:
                cardalbum['COVER'] = list(
                    getListFiles(pathalbum, self.mask_artwork))[0]

            # cover tag
            if cardalbum['COVER'] == self.TEXT_NCO:
                cover = path.join(cardalbum['PATHNAME'], )
                if DBMediasTags().getImageFromTag(cover):
                    cardalbum['COVER'] = cover
                    cardalbum['PIC'] = 1

            # length tag & genres
            liststyles = []
            seconds = 0
            for cardtrack in listcardtrack:
                seconds += cardtrack['LENGTHSECONDS']
                if cardtrack['GENRE'] is not None:
                    genres = cardtrack['GENRE']
                    genres = genres.replace(';', '/').replace(
                        ',', '/').replace('"',
                                          '').replace('-',
                                                      ' ').replace('  ', ' ')
                    for genre in genres.split('/'):
                        genre = genre.strip().title()
                        if genre not in liststyles:
                            liststyles.append(genre)
            cardalbum['STYLE'] = '/'.join(liststyles)

            minutes = seconds // 60
            cardalbum['LENGTHSECONDS'] = seconds
            cardalbum['LENGTHDISPLAY'] = "%02d:%02d" % (minutes, seconds % 60)

            # number of tracks albums
            cardalbum['TRACKS'] = len(listcardtrack)

            # date
            cardalbum['ADD'] = QDateTime.currentDateTime().toString(
                'yyyy-MM-dd HH:mm:ss')
            cardalbum['MODIFIED'] = QDateTime.currentDateTime().toString(
                'yyyy-MM-dd HH:mm:ss')

            # clean album name
            cleanfind = match(r'.*([-][1-2][0-9]{3})', cardalbum['NAME'])
            if cleanfind:
                self.signaltxt.emit('WARNING : clean : ' + cardalbum['NAME'],
                                    2)
                cardalbum['NAME'] = self.cleanfolderalbum(cardalbum['NAME'])
            if cardalbum['NAME'].endswith('-'):
                cardalbum['NAME'] = cardalbum['NAME'][:-1]

            # cover from multiple pics
            if cardalbum['COVER'] == self.TEXT_NCO and cardalbum['PIC'] > 1:
                listcovers = list(getListFiles(pathalbum, self.mask_artwork))
                for listcover in listcovers:
                    if 'front' in listcover.lower():
                        cardalbum['COVER'] = listcover

        return cardalbum, listcardtrack

    def displayCardAlbum(self, cardalbum):
        """Display CardAlbum."""
        print('-', '______----ALBUM----______')
        for key, value in cardalbum.items():
            print(f'{key:<15} = {value}')

    def cleanfolderalbum(self, albumname):
        """Clean folder album name WEB."""
        albumtempo = albumname.replace("-psy-music.ru", "").replace(
            "_", " ").replace(".", " ").replace("--", "-")
        yearfind = match(r'.*([-][1-2][0-9]{3})', albumtempo)
        albumtempo = yearfind.group(0)[:-5]
        if albumtempo.find(' - ') > 0:
            arrayalbum = albumtempo.split(' - ')
        else:
            arrayalbum = albumtempo.split('-')
        numbertirets = len(arrayalbum)
        if numbertirets == 1:
            albumtempo = arrayalbum[0].strip()
        else:
            albumtempo = arrayalbum[0].strip() + ' - ' + arrayalbum[1].strip()
        #if numbertirets == 2:
        #	albumtempo = arrayalbum[0].strip() + '-' + arrayalbum[1].strip() + "[" + arrayalbum[2].strip() + "]"
        return albumtempo
示例#5
0
class ReleaseInvent(QObject):
    signalrun = pyqtSignal(int, str)  # percent / message
    signaltxt = pyqtSignal(str, int)  # message / level display
    signalend = pyqtSignal()
    signalmacroend = pyqtSignal()

    PATH_PROG = path.dirname(path.abspath(__file__))
    FILE__INI = 'DBAlbums.json'
    Json_params = JsonParams(FILE__INI)
    group_dbalbums = Json_params.getMember('dbalbums')
    WIDT_PICM = group_dbalbums['thun_csize']
    TEXT_NCO = group_dbalbums['text_nocov']

    def __init__(self, list_actions, modsql):
        """Init invent, build list albums exists in database."""
        super(ReleaseInvent, self).__init__()
        self.list_action = list_actions
        self.modsql = modsql

    def executeActions(self):
        """Action for update database.
			[CATEGORY, FAMILY, 'DELETE/UPDATE/ADD', ID_CD, 'NAME', 'PATHNAME']"""
        numbersactions = len(self.list_action)
        counter = 1
        for listalbum in self.list_action:
            self.signalrun.emit((counter / numbersactions) * 100, listalbum[2])
            message = "\n- {act} ({num}/{tot}) : {nam}".format(
                act=listalbum[2],
                num=counter,
                tot=numbersactions,
                nam=listalbum[5])
            self.signaltxt.emit(message, 1)
            if listalbum[2] == 'DELETE':
                self.deleteAlbum(listalbum[3])
            elif listalbum[2] == 'UPDATE':
                #print('UPDATE', listalbum[0], listalbum[1], listalbum[5], listalbum[3])
                self.updateAlbum(listalbum[0], listalbum[1], listalbum[5],
                                 listalbum[3])
            elif listalbum[2] == 'ADD':
                #print('ADD', listalbum[0], listalbum[1], listalbum[5], listalbum[5])
                self.addAlbum(listalbum[0], listalbum[1], listalbum[5])
            else:
                self.signaltxt.emit(
                    'ERROR : Operation "' + listalbum[2] + '" error', 3)
            counter += 1
        #QApplication.processEvents()
        self.signalrun.emit(100, 'Completed')
        self.signalend.emit()

    def emitDisplayCardAlbum(self, cardalbum, cardtracks):
        self.signaltxt.emit(
            displayArrayDict([cardalbum],
                             ('ID_CD', 'CATEGORY', 'FAMILY', 'TAGMETHOD',
                              'POSITIONHDD', 'NAME')), 0)
        self.signaltxt.emit(
            displayArrayDict([cardalbum],
                             ('AUDIOTRACKS', 'TRACKS', 'LENGTHDISPLAY', 'CUE',
                              'PIC', 'SIZE', 'CD', 'YEAR', 'ISRC', 'LABEL',
                              'TAGISRC', 'TAGLABEL', 'COUNTRY')), 0)
        self.signaltxt.emit(
            displayArrayDict(
                cardtracks,
                ('TRACKORDER', 'LENGTHDISPLAY', 'ARTIST', 'TITLE', 'TYPEMEDIA',
                 'DATE', 'GENRE', 'DISC', 'FILENAME')), 0)

    def updateAlbum(self, category, family, folder, idcd):
        """Build album card."""
        # capture datas old
        oldcardalbum = DBFuncBase().sqlToArrayDict('ALBUMS', 'ID_CD', idcd)
        oldcardalbum = oldcardalbum[0]
        oldcardtracks = DBFuncBase().sqlToArrayDict('TRACKS', 'ID_CD', idcd)
        # delete old
        DBFuncBase().deleteTable("TRACKS", "ID_CD", idcd)
        DBFuncBase().deleteTable("COVERS", "ID_CD", idcd)
        # new
        analysealbum = CardAlbum()
        analysealbum.signaltxt.connect(self.infoAnalysealbum)
        cardalbum, cardtracks = analysealbum.defineAlbum(
            folder, category, family)
        # apply ID album
        for cardtrack in cardtracks:
            cardtrack['ID_CD'] = idcd
        # copy old datas  albums
        cardalbum['ID_CD'] = oldcardalbum['ID_CD']
        cardalbum['SCORE'] = oldcardalbum['SCORE']
        cardalbum['ADD'] = oldcardalbum['ADD']
        # copy score track
        for oldcardtrack in oldcardtracks:
            if oldcardtrack['SCORE'] > 0:
                print("score")
                # copy score
                for cardtrack in cardtracks:
                    if cardtrack['FILENAME'] == oldcardtrack[
                            'FILENAME'] and cardtrack[
                                'TRACKORDER'] == oldcardtrack['TRACKORDER']:
                        cardtrack['SCORE'] = oldcardtrack['SCORE']
        # write album update
        DBFuncBase().arrayCardsToSql('UPDATE', cardalbum, 'ALBUMS', 'ID_CD')
        DBFuncBase().arrayCardsToSql('INSERT', cardtracks, 'TRACKS',
                                     'ID_TRACK')
        if cardalbum['COVER'] != self.TEXT_NCO:
            DBFuncBase().imageToSql(cardalbum['COVER'], idcd, self.WIDT_PICM)
        # display consol
        self.emitDisplayCardAlbum(cardalbum, cardtracks)
        self.signalmacroend.emit()

    def addAlbum(self, category, family, folder):
        """Add New Album in database."""
        analysealbum = CardAlbum()
        analysealbum.signaltxt.connect(self.infoAnalysealbum)
        cardalbum, cardtracks = analysealbum.defineAlbum(
            folder, category, family)
        DBFuncBase().arrayCardsToSql('INSERT', cardalbum, 'ALBUMS', 'ID_CD')
        # last id for cardtracks
        #request = "SELECT LAST_INSERT_ID() as lastid;"
        request = getrequest('lastid', self.modsql)
        print(request)
        idcd = DBFuncBase().sqlToArray(request)[0]
        for cardtrack in cardtracks:
            cardtrack['ID_CD'] = idcd
        DBFuncBase().arrayCardsToSql('INSERT', cardtracks, 'TRACKS',
                                     'ID_TRACK')
        if cardalbum['COVER'] != self.TEXT_NCO:
            DBFuncBase().imageToSql(cardalbum['COVER'], idcd, self.WIDT_PICM)
        # display consol
        self.emitDisplayCardAlbum(cardalbum, cardtracks)
        self.signalmacroend.emit()

    def deleteAlbum(self, idcd):
        """Delete Album in database."""
        DBFuncBase().deleteTable("ALBUMS", "ID_CD", idcd)
        DBFuncBase().deleteTable("TRACKS", "ID_CD", idcd)
        DBFuncBase().deleteTable("COVERS", "ID_CD", idcd)
        self.signalmacroend.emit()

    def infoAnalysealbum(self, text, level):
        self.signaltxt.emit(text, level)
示例#6
0
class DBloadingGui(QWidget, Ui_LoadingWindow):
    PATH_PROG = path.dirname(path.abspath(__file__))
    RESS_LOGO = path.join(PATH_PROG, 'IMG')
    chdir(PATH_PROG)

    FILE__INI = 'DBAlbums.json'
    Json_params = JsonParams(FILE__INI)
    group_dbalbums = Json_params.getMember('dbalbums')
    LOGO = group_dbalbums['progr_logo']
    FONT_MAI = group_dbalbums['font00_ttx']

    def __init__(self, modsql, title, parent):
        super(DBloadingGui, self).__init__(parent)
        self.setupUi(self)
        self.parent = parent
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.setWindowFlags(Qt.SplashScreen)
        centerWidget(self)
        # font
        font = QFont()
        font.setFamily(self.FONT_MAI)
        font.setFixedPitch(True)
        font.setPointSize(14)
        self.lab_text.setFont(font)
        self.tabWidget.currentChanged.connect(self.chgtLogo)
        # logo gif
        self.numlogo = 1
        self.movielogo = QMovie(path.join(self.RESS_LOGO, "logo1.gif"))
        self.lab_logo.setMovie(self.movielogo)
        self.movielogo.start()
        # tab1
        req = DBFuncBase().buildReqTCD("CATEGORY", "FAMILY", "ALBUMS", "ALBUM",
                                       "1", True, modsql)
        self.buildTab(req, self.tableWid1)
        # tab2
        req = DBFuncBase().buildReqTCD("CATEGORY", "FAMILY", "ALBUMS",
                                       "SIZE (GO)", "ROUND( `Size` /1024,1)",
                                       True, modsql)
        self.buildTab(req, self.tableWid2)
        # tab3
        req = DBFuncBase().buildReqTCD("YEAR", "CATEGORY", "ALBUMS", "YEAR",
                                       "1", True, modsql)
        self.buildTab(req, self.tableWid3)
        # message
        basedate = DBFuncBase().sqlToArray(getrequest('datedatabase', modsql))
        if len(basedate) == 0:
            txt_message = modsql + " Base \nlast modified :\nnever"
        elif isinstance(basedate[0], QDateTime):
            txt_message = modsql + " Base \nlast modified :\n" + basedate[
                0].toString('dd/MM/yyyy hh:mm:ss')
        else:
            txt_message = modsql + " Base \nlast modified :\n" + basedate[
                0].replace('T', ' ')
        self.lab_text.setText(title + "\nConnected " + txt_message)
        # quit
        self.btn_quit.clicked.connect(lambda: self.hide())
        # theme
        self.applyTheme()

    @pyqtSlot()
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape or event.key() == Qt.Key_F1:
            self.hide()

    def buildTab(self, req, tab):
        model = QSqlQueryModel(self)
        model.setQuery(req)
        tab.setModel(model)
        tab.resizeColumnsToContents()
        tab.verticalHeader().setVisible(False)
        tab.horizontalHeader().setStretchLastSection(True)
        tab.verticalHeader().setDefaultSectionSize(self.parent.C_HEIGHT)

    def chgtLogo(self):
        self.movielogo.stop()
        self.numlogo += 1
        self.numlogo = self.numlogo % 3
        logo = path.join(self.RESS_LOGO, "logo" + str(self.numlogo) + ".gif")
        self.movielogo = QMovie(logo)
        self.lab_logo.setMovie(self.movielogo)
        self.movielogo.start()

    def applyTheme(self):
        """Apply color Theme to main Gui."""
        # main
        mainstyle = 'QWidget{{background-color: {col2};}}' \
           'QScrollBar:vertical{{width: 14px;}}' \
           'QScrollBar:horizontal{{height: 14px;}}'
        mainstyle = mainstyle.format(col2=self.parent.curthe.listcolors[1])
        self.setStyleSheet(mainstyle)
        gridstyle = 'alternate-background-color: {col3};background-color: {col4};'
        gridstyle = gridstyle.format(col3=self.parent.curthe.listcolors[2],
                                     col4=self.parent.curthe.listcolors[3])
        self.tableWid1.setStyleSheet(gridstyle)
        self.tableWid2.setStyleSheet(gridstyle)
        self.tableWid3.setStyleSheet(gridstyle)
示例#7
0
class DBAlbumsQT5Mini(QMainWindow):
    """Init mini Gui constants."""
    PATH_PROG = path.dirname(path.abspath(__file__))
    RESS_ICOS = path.join(PATH_PROG, 'IMG', 'ICO')
    chdir(PATH_PROG)
    VERS_PROG = '1.01'
    TITL_PROG = "♫ DBAlbums mini v{v} (2017)".format(v=VERS_PROG)
    FILE__INI = 'DBAlbums.json'
    Json_params = JsonParams(FILE__INI)
    group_dbalbums = Json_params.getMember('dbalbums')
    WINS_ICO = path.join(PATH_PROG, 'IMG', group_dbalbums['wins_icone'])
    PICM_NCO = path.join(PATH_PROG, 'IMG', group_dbalbums['pict_blank'])
    THEM_COL = group_dbalbums['name_theme']
    ENVT_DEF = group_dbalbums['envt_deflt']

    def __init__(self, parent=None):
        super(DBAlbumsQT5Mini, self).__init__(parent)
        self.setWindowIcon(QIcon(self.WINS_ICO))
        self.setWindowTitle(self.TITL_PROG + ' : [' + self.ENVT_DEF + ']')
        self.h_main = 400
        self.resize(1248, self.h_main)
        centerWidget(self)

        self.menua = QMenu()
        self.action_OPF = self.menua.addAction(
            self.style().standardIcon(QStyle.SP_DialogOpenButton),
            "Open Folder...", self.getFolder)

        self.textsearch = QLineEdit()
        self.textsearch.setFixedSize(170, 22)
        self.statusBar().addPermanentWidget(self.textsearch)
        self.textsearch.textChanged.connect(self.onFiltersChanged)

        self.btn_style = QPushButton()
        self.btn_style.setIcon(self.style().standardIcon(
            QStyle.SP_DialogResetButton))
        self.btn_style.setStyleSheet("border: none;")
        self.btn_style.clicked.connect(
            lambda: [self.curthe.nextTheme(),
                     self.applyTheme()])
        self.statusBar().addPermanentWidget(self.btn_style)

        boolconnect, self.dbbase, self.modsql, self.rootDk, self.lstcat = connectDatabase(
            self.ENVT_DEF)

        autoList = DBFuncBase().sqlToArray(
            getrequest('autocompletion', self.modsql))
        self.com_autcom = QCompleter(autoList, self.textsearch)
        self.com_autcom.setCaseSensitivity(Qt.CaseInsensitive)
        self.textsearch.setCompleter(self.com_autcom)

        self.mytable = QTableView(self)
        self.mytable.setAlternatingRowColors(True)
        self.mytable.setSortingEnabled(True)
        self.mytable.setSelectionBehavior(QTableView.SelectRows)
        self.mytable.setSelectionMode(QAbstractItemView.SingleSelection)
        self.mytable.doubleClicked.connect(self.onSelect)
        self.mytable.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mytable.customContextMenuRequested.connect(self.popUpTreeAlbums)

        self.curthe = ThemeColors(self.THEM_COL)
        self.applyTheme()

        req = getrequest('albumslist', self.modsql)
        self.model = ModelTableAlbumsABS(self, req)
        self.model.SortFilterProxy.layoutChanged.connect(self.listChanged)
        self.model.SortFilterProxy.sort(-1)
        self.mytable.setModel(self.model.SortFilterProxy)

        # width columns
        for ind in range(len(self.model.A_C_WIDTH)):
            self.mytable.setColumnWidth(ind, self.model.A_C_WIDTH[ind])
        # height rows
        self.mytable.verticalHeader().setDefaultSectionSize(
            self.model.C_HEIGHT)

        self.displayTitle()
        self.setCentralWidget(self.mytable)

    def onFiltersChanged(self):
        self.model.SortFilterProxy.updateFilters(self.textsearch.text())
        self.displayTitle()

    def onSelect(self):
        indexes = self.mytable.selectedIndexes()
        indexes = self.model.SortFilterProxy.mapToSource(indexes[0])
        self.currow = indexes.row()
        albumname = self.model.getData(self.currow, 'NAME')
        idcd = self.model.getData(self.currow, 'ID_CD')
        coveral = DBFuncBase().sqlToPixmap(idcd, self.PICM_NCO)
        CoverViewGui(coveral, albumname, self.h_main, self.h_main)

    def popUpTreeAlbums(self, position):
        self.menua.exec_(self.mytable.viewport().mapToGlobal(position))

    def getFolder(self):
        """Open album folder."""
        indexes = self.mytable.selectedIndexes()
        indexes = self.model.SortFilterProxy.mapToSource(indexes[0])
        self.currow = indexes.row()
        albumpath = self.model.getData(self.currow, 'PATHNAME')
        openFolder(albumpath)

    def listChanged(self):
        pass

    def displayTitle(self):
        if int(((self.model.SortFilterProxy.cpt_len / 60 / 60) / 24) *
               10) / 10 < 1:
            # seoncd -> Hours
            txt_len = str(
                int(((self.model.SortFilterProxy.cpt_len / 60 / 60)) * 10) /
                10) + ' Hours'
        else:
            # seoncd -> Days
            txt_len = str(
                int(((self.model.SortFilterProxy.cpt_len / 60 / 60) / 24) * 10)
                / 10) + ' Days'
        if int(self.model.SortFilterProxy.cpt_siz / 1024) == 0:
            txt_siz = str(self.model.SortFilterProxy.cpt_siz) + ' Mo'
        else:
            txt_siz = str(int(
                self.model.SortFilterProxy.cpt_siz / 1024)) + ' Go'
        txt_sch = (self.textsearch.text()
                   if len(self.textsearch.text()) > 0 else 'all')
        message = "Search Result \"{sch}\" :  {alb} | {trk} | {cds} | {siz} | {dur}"
        message = message.format(
            alb=displayCounters(self.model.SortFilterProxy.rowCount(),
                                'Album'),
            cds=displayCounters(self.model.SortFilterProxy.cpt_cds, 'CD'),
            trk=displayCounters(self.model.SortFilterProxy.cpt_trk, 'Track'),
            siz=txt_siz,
            dur=txt_len,
            sch=txt_sch)
        self.statusBar().showMessage(message)  # setsetWindowTitle(message)

    def applyTheme(self):
        """Apply color Theme to main Gui."""
        # main
        mainstyle = 'QMainWindow{{background-color: {col1};border: 1px solid black;}}' \
           'QLineEdit{{background-color: {col2};}}' \
           'QStatusBar{{background-color: {col1};border: 1px solid black;}}' \
           'QScrollBar:vertical{{width: 14px;}}' \
           'QScrollBar:horizontal{{height: 14px;}}' \
           'QTableView{{alternate-background-color: {col3};background-color: {col4};}}' \
           'QTableView::item:selected{{ background-color:{col5}; color:white;}}'
        mainstyle = mainstyle.format(col1=self.curthe.listcolors[0],
                                     col2=self.curthe.listcolors[1],
                                     col3=self.curthe.listcolors[2],
                                     col4=self.curthe.listcolors[3],
                                     col5=self.curthe.listcolors[4])
        self.setStyleSheet(mainstyle)
        # treeview
        gridstyle = 'QHeaderView::section{{background-color: {col2};border-radius:1px;margin: 1px;padding: 2px;}}'
        gridstyle = gridstyle.format(col2=self.curthe.listcolors[1])
        self.mytable.setStyleSheet(gridstyle)