Ejemplo n.º 1
0
class Main(QtGui.QMainWindow):
    __settings = QSettings(u'gayeogi', u'gayeogi')
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.statistics = None
        if not os.path.exists(dbPath):
            os.mkdir(dbPath)
        self.db = DB()
        from interfaces.main import Ui_main
        self.ui = Ui_main()
        widget = QtGui.QWidget()
        self.ui.setupUi(widget)
        self.ui.artists.setHeaderLabels([u'Artist'])
        self.ui.artists.itemSelectionChanged.connect(self.fillAlbums)
        delegate = ADRItemDelegate()
        self.ui.artists.setItemDelegateForColumn(0, delegate)
        self.ui.albums = ADRTreeWidget()
        self.ui.albums.setHeaderLabels([u'Year', u'Album'])
        self.ui.albums.buttonClicked.connect(self.setAnalog)
        self.ui.albums.itemSelectionChanged.connect(self.fillTracks)
        self.ui.verticalLayout_4.addWidget(self.ui.albums)
        self.ui.tracks.setHeaderLabels(['#', u'Title'])
        self.ui.plugins = {}
        self.ui.splitter.restoreState(
                self.__settings.value(u'splitters').toByteArray())
        self.setCentralWidget(widget)
        self.library = (version, {}, {}, {}, {}, [False])
        self.ignores = self.__settings.value(u'ignores', []).toPyObject()
        if self.ignores == None:
            self.ignores = []
        if not os.path.exists(os.path.join(dbPath, u'db.pkl')):
            dialog = Settings()
            dialog.exec_()
        else:
            self.library = self.db.read()
            self.update()
        directory = self.__settings.value(u'directory', []).toPyObject()
        if type(directory) != list:
            directory = [(unicode(directory), 2)]
        self.fs = Filesystem(directory, self.library, self.ignores)
        self.fs.stepped.connect(self.statusBar().showMessage)
        self.fs.updated.connect(self.update)
        self.rt = Distributor(self.library)
        self.rt.stepped.connect(self.statusBar().showMessage)
        self.rt.updated.connect(self.update)
        self.ui.local.clicked.connect(self.local)
        self.ui.remote.clicked.connect(self.remote)
        self.ui.close.clicked.connect(self.close)
        self.ui.save.clicked.connect(self.save)
        self.ui.settings.clicked.connect(self.showSettings)
        self.ui.artistFilter.textEdited.connect(self.filter_)
        self.ui.albumFilter.textEdited.connect(self.filter_)
        self.ui.trackFilter.textEdited.connect(self.filter_)
        self.statusBar()
        self.setWindowTitle(u'gayeogi ' + version)
        self.translators = list()
        self.loadPluginsTranslators()
        self.loadPlugins()
    def disableButtons(self):
        u"""Disable some buttons one mustn't use during the update.

        Note: They are then re-enabled in the update() method.
        """
        self.ui.local.setDisabled(True)
        self.ui.remote.setDisabled(True)
        self.ui.save.setDisabled(True)
        self.ui.settings.setDisabled(True)
    def local(self):
        u"""Start local database update."""
        self.disableButtons()
        self.fs.start()
    def remote(self):
        u"""Start remote databases update."""
        self.disableButtons()
        self.rt.start()
    def loadPluginsTranslators(self):
        reload(gayeogi.plugins)
        app = QtGui.QApplication.instance()
        for plugin in gayeogi.plugins.__all__:
            translator = QTranslator()
            if translator.load(plugin + u'_' + locale,
                    os.path.join(lnPath, u'plugins', u'langs')):
                self.translators.append(translator)
                app.installTranslator(translator)
    def removePluginsTranslators(self):
        app = QtGui.QApplication.instance()
        for translator in self.translators:
            app.removeTranslator(translator)
    def loadPlugins(self):
        def depends(plugin):
            for p in gayeogi.plugins.__all__:
                class_ = getattr(gayeogi.plugins, p).Main
                if plugin in class_.depends and class_.loaded:
                    return True
            return False
        for plugin in gayeogi.plugins.__all__:
            class_ = getattr(gayeogi.plugins, plugin).Main
            __settings_ = QSettings(u'gayeogi', class_.name)
            option = __settings_.value(u'enabled', 0).toInt()[0]
            if option and not class_.loaded:
                class__ = class_(self.ui, self.library, self.appendPlugin,
                        self.removePlugin)
                class__.load()
                self.ui.plugins[plugin] = class__
            elif not option and class_.loaded:
                self.ui.plugins[plugin].unload()
                for d in self.ui.plugins[plugin].depends:
                    if not self.ui.plugins[d].loaded \
                            and d in self.ui.plugins.keys():
                        del self.ui.plugins[d]
                if not depends(plugin):
                    del self.ui.plugins[plugin]
    def appendPlugin(self, parent, child, position):
        parent = getattr(self.ui, parent)
        if position == 'start':
            position = 0
        elif position == 'end':
            position = len(parent.parent().children()) - 7
        if isinstance(parent, QtGui.QLayout):
            widget = parent.itemAt(position)
            if not widget:
                parent.insertWidget(position, child)
            else:
                if isinstance(widget, QtGui.QTabWidget):
                    widget.addTab(child, child.name)
                else:
                    try:
                        widget.name
                    except AttributeError:
                        parent.insertWidget(position, child)
                    else:
                        widget = parent.takeAt(position).widget()
                        tab = QtGui.QTabWidget()
                        tab.setTabPosition(tab.South)
                        tab.addTab(widget, widget.name)
                        tab.addTab(child, child.name)
                        parent.insertWidget(position, tab)
    def removePlugin(self, parent, child, position):
        parent = getattr(self.ui, parent)
        if position == 'start':
            position = 0
        elif position == 'end':
            position = len(parent.parent().children()) - 8
        if isinstance(parent, QtGui.QLayout):
            widget = parent.itemAt(position).widget()
            try:
                if widget.name == child.name:
                    parent.takeAt(position).widget().deleteLater()
            except AttributeError:
                for i in range(widget.count()):
                    if widget.widget(i).name == child.name:
                        widget.removeTab(i)
                if widget.count() == 1:
                    tmp = widget.widget(0)
                    parent.takeAt(position).widget().deleteLater()
                    parent.insertWidget(position, tmp)
                    parent.itemAt(position).widget().show()
    def filter_(self, text):
        columns = list()
        arguments = list()
        adr = [u'a', u'd', u'r', u'not a', u'not d', u'not r']
        num_adr = dict()
        __num_adr = {
            u'a': 123,
            u'd': 234,
            u'r': 345
        }
        for a in unicode(text).split(u'|'):
            temp = a.split(u':')
            if len(temp) == 1 and temp[0] in adr:
                temp2 = temp[0].split(u' ')
                if len(temp2) == 2:
                    num_adr[temp2[1]] = False
                else:
                    num_adr[temp2[0]] = True
                continue
            if len(temp) != 2 or temp[1] == u'':
                break
            columns.append(temp[0].lower())
            arguments.append(temp[1].lower())
        tree = self.sender().parent().children()[2]
        if (len(columns) != 0 and len(columns) == len(arguments)) or num_adr:
            header = tree.header().model()
            num_columns = [i for i in range(tree.columnCount())
                if unicode(header.headerData(i,
                    Qt.Horizontal).toString()).lower() in columns]
            adr_column = -1
            if num_adr:
                item = tree.topLevelItem(0)
                for i in range(item.columnCount()):
                    if item.data(i, 987).toString():
                        adr_column = i
                        break
            for i in range(tree.topLevelItemCount()):
                item = tree.topLevelItem(i)
                hidden = list()
                for j, c in enumerate(num_columns):
                    try:
                        if item not in hidden:
                            if not re.search(arguments[j],
                            unicode(item.text(c)).lower()):
                                item.setHidden(True)
                                item.setSelected(False)
                                hidden.append(item)
                            else:
                                item.setHidden(False)
                    except:
                        pass
                if adr_column != -1 and item not in hidden:
                    for adr, v in num_adr.iteritems():
                        if item.data(adr_column, __num_adr[adr]).toBool() == v:
                            item.setHidden(False)
                        else:
                            item.setHidden(True)
                            item.setSelected(False)
                            hidden.append(item)
        else:
            for i in range(tree.topLevelItemCount()):
                tree.topLevelItem(i).setHidden(False)
    def showSettings(self):
        u"""Show settings dialog and then update accordingly."""
        def __save():
            directory = self.__settings.value(u'directory', []).toPyObject()
            if type(directory) != list:
                directory = [(unicode(directory), 2)]
            self.ignores = self.__settings.value(u'ignores', []).toPyObject()
            self.fs.actualize(directory, self.ignores)
            self.removePluginsTranslators()
            self.loadPluginsTranslators()
            self.loadPlugins()
        dialog = Settings()
        dialog.ok.clicked.connect(__save)
        dialog.exec_()
    def save(self):
        u"""Save database to file."""
        try:
            self.library[5][0] = False
            self.db.write(self.library)
        except AttributeError:
            self.statusBar().showMessage(self.trUtf8('Nothing to save...'))
        else:
            self.statusBar().showMessage(self.trUtf8('Saved'))
    def setAnalog(self, item):
        data = not item.data(1, 123).toBool()
        item.setData(1, 123, data)
        self.library[4][item.artist + unicode(item.text(0))
                + unicode(item.data(1, 987).toString())][u'analog'] = data
        if data:
            self.statistics[u'albums'][0] += 1
            switch = True
            for y, d in self.library[1][item.artist].iteritems():
                for a in d.keys():
                    if not self.library[4][item.artist + y + a][u'analog']:
                        switch = False
                        break
                if not switch:
                    break
            if switch:
                self.statistics[u'artists'][0] += 1
                self.ui.artistsGreen.setText(
                        unicode(self.statistics[u'artists'][0]))
                self.statistics[u'detailed'][item.artist][u'a'] = True
                self.ui.artists.topLevelItem(item.aIndex).setData(0, 123, True)
        else:
            self.statistics[u'albums'][0] -= 1
            if self.ui.artists.topLevelItem(item.aIndex).data(0, 123).toBool():
                self.statistics[u'artists'][0] -= 1
                self.ui.artistsGreen.setText(
                        unicode(self.statistics[u'artists'][0]))
                self.statistics[u'detailed'][item.artist][u'a'] = False
                self.ui.artists.topLevelItem(item.aIndex).setData(0, 123, False)
        self.ui.albumsGreen.setText(unicode(self.statistics[u'albums'][0]))
    def update(self):
        self.computeStats()
        self.statusBar().showMessage(self.trUtf8('Done'))
        self.ui.local.setEnabled(True)
        self.ui.remote.setEnabled(True)
        self.ui.save.setEnabled(True)
        self.ui.settings.setEnabled(True)
        sArtists = [i.text(0) for i in self.ui.artists.selectedItems()]
        sAlbums = [i.text(1) for i in self.ui.albums.selectedItems()]
        sTracks = [i.text(0) for i in self.ui.tracks.selectedItems()]
        self.ui.artists.clear()
        self.ui.artists.setSortingEnabled(False)
        for i, l in enumerate(self.library[1].keys()):
            item = QtGui.QTreeWidgetItem([l])
            item.setData(0, 123, self.statistics[u'detailed'][l][u'a'])
            item.setData(0, 234, self.statistics[u'detailed'][l][u'd'])
            item.setData(0, 345, self.statistics[u'detailed'][l][u'r'])
            item.setData(0, 987, l)
            self.ui.artists.insertTopLevelItem(i, item)
        self.ui.artists.setSortingEnabled(True)
        self.ui.artists.sortItems(0, 0)
        for i in range(3):
            self.ui.artists.resizeColumnToContents(i)
        self.ui.artistFilter.textEdited.emit(self.ui.artistFilter.text())
        for a in sArtists:
            i = self.ui.artists.findItems(a, Qt.MatchExactly)
            if i:
                i[0].setSelected(True)
        for a in sAlbums:
            i = self.ui.albums.findItems(a, Qt.MatchExactly, 1)
            if i:
                i[0].setSelected(True)
        for a in sTracks:
            i = self.ui.tracks.findItems(a, Qt.MatchExactly)
            if i:
                i[0].setSelected(True)
        self.ui.artistsGreen.setText(unicode(self.statistics[u'artists'][0]))
        self.ui.artistsYellow.setText(unicode(self.statistics[u'artists'][1]))
        self.ui.artistsRed.setText(unicode(self.statistics[u'artists'][2]))
        self.ui.albumsGreen.setText(unicode(self.statistics[u'albums'][0]))
        self.ui.albumsYellow.setText(unicode(self.statistics[u'albums'][1]))
        self.ui.albumsRed.setText(unicode(self.statistics[u'albums'][2]))
    def fillAlbums(self):
        items = self.ui.artists.selectedItems()
        self.ui.albums.clear()
        self.ui.albums.setSortingEnabled(False)
        for item in items:
            artist = unicode(item.data(0, 987).toString())
            for date, albums in self.library[1][artist].iteritems():
                for album, data in albums.iteritems():
                    key = self.library[4][artist + date + album]
                    item_ = QtGui.QTreeWidgetItem([date, album])
                    item_.artist = artist
                    item_.aIndex = self.ui.artists.indexOfTopLevelItem(item)
                    item_.setData(1, 123, key[u'analog'])
                    item_.setData(1, 234, key[u'digital'])
                    item_.setData(1, 345, key[u'remote'] and True or False)
                    item_.setData(1, 987, album)
                    self.ui.albums.addTopLevelItem(item_)
        self.ui.albums.setSortingEnabled(True)
        self.ui.albums.sortItems(0, 0)
        for i in range(4):
            self.ui.albums.resizeColumnToContents(i)
        self.ui.albumFilter.textEdited.emit(self.ui.albumFilter.text())
    def fillTracks(self):
        items = self.ui.albums.selectedItems()
        self.ui.tracks.clear()
        self.ui.tracks.setSortingEnabled(False)
        for item in items:
            date = unicode(item.text(0))
            album = unicode(item.data(1, 987).toString())
            for num, titles in self.library[1][item.artist] \
                    [date][album].iteritems():
                for title in titles.keys():
                    item_ = NumericTreeWidgetItem([num, title])
                    item_.album = album
                    item_.year = date
                    item_.artist = item.artist
                    self.ui.tracks.addTopLevelItem(item_)
        self.ui.tracks.setSortingEnabled(True)
        self.ui.tracks.sortItems(0, 0)
        self.ui.tracks.resizeColumnToContents(0)
        self.ui.tracks.resizeColumnToContents(1)
        self.ui.trackFilter.textEdited.emit(self.ui.trackFilter.text())
    def computeStats(self):
        artists = [0, 0, 0]
        albums = [0, 0, 0]
        detailed = dict()
        for a, d in self.library[1].iteritems():
            detailed[a] = dict()
            aa = 1
            ad = 1
            ar = 1
            for y, t in d.iteritems():
                for al in t.keys():
                    key = self.library[4][a + y + al]
                    analog = int(key[u'analog'])
                    digital = int(key[u'digital'])
                    remote = int(bool(key[u'remote']))
                    albums[0] += analog
                    albums[1] += digital
                    albums[2] += remote
                    if not analog:
                        aa = 0
                    if not digital:
                        ad = 0
                    if not remote:
                        ar = 0
            detailed[a][u'a'] = bool(aa)
            detailed[a][u'd'] = bool(ad)
            detailed[a][u'r'] = bool(ar)
            artists[0] += aa
            artists[1] += ad
            artists[2] += ar
        self.statistics = {
            u'artists': artists,
            u'albums': albums,
            u'detailed': detailed
        }
    def closeEvent(self, event):
        def unload():
            for plugin in self.ui.plugins.values():
                plugin.unload()
            self.__settings.setValue(u'splitters', self.ui.splitter.saveState())
        if self.library[5][0]:
            def save():
                self.save()
            def reject():
                event.ignore()
            from interfaces.confirmation import ConfirmationDialog
            dialog = ConfirmationDialog()
            dialog.buttons.accepted.connect(save)
            dialog.buttons.accepted.connect(unload)
            dialog.buttons.rejected.connect(reject)
            dialog.buttons.helpRequested.connect(unload)
            dialog.exec_()
        else:
            unload()
Ejemplo n.º 2
0
class Main(QtGui.QMainWindow):
    __settings = QSettings(u'gayeogi', u'gayeogi')
    __dbsettings = QSettings(u'gayeogi', u'Databases')

    def __init__(self):
        super(Main, self).__init__()
        if not os.path.exists(dbPath):
            os.mkdir(dbPath)
            if os.path.exists(os.path.join(dbPath[:-3], u'db.pkl')):
                pass  # TODO: convert old db to new
            else:
                dialog = Settings()
                dialog.exec_()
        self.db = DB(dbPath)
        self.db.finished.connect(self.enableButtons)
        self.db.artistsStatisticsChanged.connect(self.updateArtistsStatistics)
        self.db.albumsStatisticsChanged.connect(self.updateAlbumsStatistics)
        from interfaces.main import Ui_main
        self.ui = Ui_main()
        widget = QtGui.QWidget()
        self.ui.setupUi(widget)
        self.ui.artists = View(self.db.artists, TableView(
            self.__settings.value(u'artistsView').toByteArray()
        ), Main.__dbsettings.value(
            u'image/artist/enabled', 2
        ).toBool(), self.ui.splitter)
        delegate = ADRItemDelegate()
        self.ui.artists.view.setItemDelegateForColumn(0, delegate)
        self.ui.albums = View(self.db.albums, ADRTableView(
            self.__settings.value(u'albumsView').toByteArray()
        ), Main.__dbsettings.value(
            u'image/album/enabled', 2
        ).toBool(), self.ui.splitter)
        self.ui.tracks = View(self.db.tracks, TableView(
            self.__settings.value(u'tracksView').toByteArray()
        ), None, self.ui.splitter)
        self.ui.tracks.view.setAlternatingRowColors(True)
        self.ui.artists.view.selectionModel().selectionChanged.connect(
            self.ui.albums.model.setSelection
        )
        self.ui.albums.view.selectionModel().selectionChanged.connect(
            self.ui.tracks.model.setSelection
        )
        self.ui.plugins = {}
        self.ui.splitter.restoreState(
            self.__settings.value(u'splitters').toByteArray()
        )
        self.setCentralWidget(widget)
        self.rt = Distributor(self.db.iterator())
        self.rt.stepped.connect(self.statusBar().showMessage)
        self.rt.finished.connect(self.enableButtons)
        self.ui.local.clicked.connect(self.disableButtons)
        self.ui.local.clicked.connect(self.db.start)
        self.ui.remote.clicked.connect(self.disableButtons)
        self.ui.remote.clicked.connect(self.rt.start)
        self.ui.close.clicked.connect(self.close)
        self.ui.save.clicked.connect(self.save)
        self.ui.settings.clicked.connect(self.showSettings)
        self.statusBar()
        self.setWindowTitle(u'gayeogi ' + __version__)
        self.translators = list()
        self.loadPluginsTranslators()
        self.loadPlugins()

    def disableButtons(self):
        """Disable some buttons one mustn't use during the update."""
        self.ui.local.setDisabled(True)
        self.ui.remote.setDisabled(True)
        self.ui.save.setDisabled(True)
        self.ui.settings.setDisabled(True)

    def enableButtons(self):
        """Enable buttons disabled by Main.disableButtons.
        Also shows the "Done" message.
        """
        self.ui.local.setEnabled(True)
        self.ui.remote.setEnabled(True)
        self.ui.save.setEnabled(True)
        self.ui.settings.setEnabled(True)
        self.statusBar().showMessage(self.trUtf8('Done'))

    def loadPluginsTranslators(self):
        reload(gayeogi.plugins)
        app = QtGui.QApplication.instance()
        for plugin in gayeogi.plugins.__all__:
            translator = QTranslator()
            if translator.load(plugin + u'_' + locale,
                    os.path.join(lnPath, u'plugins', u'langs')):
                self.translators.append(translator)
                app.installTranslator(translator)

    def removePluginsTranslators(self):
        app = QtGui.QApplication.instance()
        for translator in self.translators:
            app.removeTranslator(translator)

    def loadPlugins(self):
        def depends(plugin):
            for p in gayeogi.plugins.__all__:
                class_ = getattr(gayeogi.plugins, p).Main
                if plugin in class_.depends and class_.loaded:
                    return True
            return False
        for plugin in gayeogi.plugins.__all__:
            class_ = getattr(gayeogi.plugins, plugin).Main
            __settings_ = QSettings(u'gayeogi', class_.name)
            option = __settings_.value(u'enabled', 0).toInt()[0]
            if option and not class_.loaded:
                class__ = class_(self.ui, self.db.artists, self.appendPlugin,
                        self.removePlugin)
                class__.load()
                self.ui.plugins[plugin] = class__
            elif not option and class_.loaded:
                self.ui.plugins[plugin].unload()
                for d in self.ui.plugins[plugin].depends:
                    if not self.ui.plugins[d].loaded \
                            and d in self.ui.plugins.keys():
                        del self.ui.plugins[d]
                if not depends(plugin):
                    del self.ui.plugins[plugin]

    def appendPlugin(self, parent, child, position):
        parent = getattr(self.ui, parent)
        if position == 'start':
            position = 0
        elif position == 'end':
            position = len(parent.parent().children()) - 7
        if isinstance(parent, QtGui.QLayout):
            widget = parent.itemAt(position)
            if not widget:
                parent.insertWidget(position, child)
            else:
                if isinstance(widget, QtGui.QTabWidget):
                    widget.addTab(child, child.name)
                else:
                    try:
                        widget.name
                    except AttributeError:
                        parent.insertWidget(position, child)
                    else:
                        widget = parent.takeAt(position).widget()
                        tab = QtGui.QTabWidget()
                        tab.setTabPosition(tab.South)
                        tab.addTab(widget, widget.name)
                        tab.addTab(child, child.name)
                        parent.insertWidget(position, tab)

    def removePlugin(self, parent, child, position):
        parent = getattr(self.ui, parent)
        if position == 'start':
            position = 0
        elif position == 'end':
            position = len(parent.parent().children()) - 8
        if isinstance(parent, QtGui.QLayout):
            widget = parent.itemAt(position).widget()
            try:
                if widget.name == child.name:
                    parent.takeAt(position).widget().deleteLater()
            except AttributeError:
                for i in range(widget.count()):
                    if widget.widget(i).name == child.name:
                        widget.removeTab(i)
                if widget.count() == 1:
                    tmp = widget.widget(0)
                    parent.takeAt(position).widget().deleteLater()
                    parent.insertWidget(position, tmp)
                    parent.itemAt(position).widget().show()

    def showSettings(self):
        u"""Show settings dialog and then update accordingly."""
        def __save():
            self.removePluginsTranslators()
            self.loadPluginsTranslators()
            self.loadPlugins()
        dialog = Settings()
        dialog.ok.clicked.connect(__save)
        dialog.exec_()

    def save(self):
        u"""Save database to file."""
        self.db.save()
        self.statusBar().showMessage(self.trUtf8('Saved'))

    def updateArtistsStatistics(self, a, d, r):
        """Updates global artists' statistics.

        :a: A statistics.
        :d: D statistics.
        :r: R statistics.
        """
        self.ui.artistsGreen.setText(unicode(a))
        self.ui.artistsYellow.setText(unicode(d))
        self.ui.artistsRed.setText(unicode(r))

    def updateAlbumsStatistics(self, a, d, r):
        """Updated global albums' statistics.

        @note: Attributes as in Main.updateArtistsStatistics.
        """
        self.ui.albumsGreen.setText(unicode(a))
        self.ui.albumsYellow.setText(unicode(d))
        self.ui.albumsRed.setText(unicode(r))

    def closeEvent(self, event):
        def unload():
            for plugin in self.ui.plugins.values():
                plugin.unload()
            self.__settings.setValue(
                u'splitters', self.ui.splitter.saveState()
            )
            self.__settings.setValue(u'artistsView',
                self.ui.artists.view.horizontalHeader().saveState()
            )
            self.__settings.setValue(u'albumsView',
                self.ui.albums.view.horizontalHeader().saveState()
            )
            self.__settings.setValue(u'tracksView',
                self.ui.tracks.view.horizontalHeader().saveState()
            )
        if self.db.modified:
            from interfaces.confirmation import ConfirmationDialog
            dialog = ConfirmationDialog()
            dialog.buttons.accepted.connect(self.save)
            dialog.buttons.accepted.connect(unload)
            dialog.buttons.rejected.connect(event.ignore)
            dialog.buttons.helpRequested.connect(unload)
            dialog.exec_()
        else:
            unload()