示例#1
0
class QPackagesModel(QtCore.QAbstractTableModel):
    """
        Model used to handle the packages listed in a .ini file
    """
    def __init__(self, inifile):
        """
            :param inifile:
                Path to the packages.ini ini file
        """
        QtCore.QAbstractTableModel.__init__(self, None)
        self.packages = []
        self.to_install = []
        self.inifile = inifile
        self.cache = Cache()

        self._populate()

    def _populate(self):
        """
            Load the inifile with the package names and description
        """
        pkg_dict = DictIni(self.inifile)
        for section, packages in pkg_dict.items():
            for pkg_name, pkg_description in packages.iteritems():
                if self.cache.has_key(pkg_name):
                    pkg = self.cache[pkg_name]
                    if pkg.is_installed:
                        status = 2
                    else:
                        status = 0
                else:
                    pkg = None
                    status = 1
                    print("This package  : '%s:%s' isn't available in your \
configured repositories" % (pkg_name, pkg_description))
                self.packages.append(
                        {'name':pkg_name,
                         'description':pkg_description,
                         'package':pkg,
                         'status':status,
                         'section':section})

        self.packages = sorted(self.packages, key=lambda a:a['status'])
        self.reset()

    def _get_pkg(self, index):
        """
            Returns a pkg object for a given index
        """
        return self.packages[index.row()]['package']

    def _init_cache(self):
        """
            Initialize our cache for apt
        """
        self.cache = Cache()

    def rowCount(self, index=None):
        """
            Required function
            Returns the number of rows
        """
        return len(self.packages)

    def columnCount(self, index=None):
        """
            Required function
            Returns the number of columns
        """
        return len(TABLE_HEADER)

    def data(self, index, role):
        """
            Required function
            Returns the model's datas
        """
        if not index.isValid() or not (0 <= index.row() < self.rowCount()):
            return QtCore.QVariant()

        column = index.column()
        package = self.packages[index.row()]

        if role == QtCore.Qt.DisplayRole:
            return self.render_cell(package, column)
        elif role == QtCore.Qt.CheckStateRole:
            return self._cell_check_status(package['package'], column)
        elif role == QtCore.Qt.BackgroundColorRole:
            return self._cell_color(package['status'])


    @staticmethod
    def render_cell(package, column):
        """
            Return the column's cell content for the given package
        """
        if column == 0:
            return package['name']
        elif column == 1:
            return package['description'].decode('utf-8')
        elif column == 2:
            if not package['package']:
                return "Not Available"

    def _cell_check_status(self, pkg, column):
        """
            Returns the row's Qchecked status
        """
        if column == 2:
            if pkg and (pkg.installed or pkg.marked_install):
                return QtCore.QVariant(QtCore.Qt.Checked)
            else:
                return QtCore.QVariant(QtCore.Qt.Unchecked)

    @staticmethod
    def _cell_color(status):
        """
            Returns the cell color
        """
        if status == 2:
            return QtGui.QColor(255, 0, 0, 127)
        elif status == 1:
            return QtGui.QColor(255, 255, 0, 127)
        elif status == 0:
            return QtGui.QColor(255, 255, 255, 127)
        else:
            return QtGui.QColor(255, 127, 0, 200)

    def setData(self, index, value, role):
        """
            Changes datas informations
        """
        if role == QtCore.Qt.CheckStateRole and index.column() == 2:
            pkg = self._get_pkg(index)
            if not pkg.installed:
                if value == QtCore.QVariant(QtCore.Qt.Checked):
                    pkg.mark_install()
                    self.packages[index.row()]['status'] = -1
                    self.to_install.append(True)
                    self.emit(QtCore.SIGNAL("dataChanged(int)"),
                              len(self.to_install))
                else:
                    pkg.mark_delete()
                    self.packages[index.row()]['status'] = 0
                    self.to_install.pop()
                    self.emit(QtCore.SIGNAL("dataChanged(int)"),
                            len(self.to_install))
                ans = True
        else:
            ans = QtCore.QAbstractTableModel.setData(self, modelIndex, variant, role)
        return ans

    def flags(self, index):
        """
            Add a flag to indicate whether a field is editable/checkable ...
        """
        if not index.isValid():
            return QtCore.Qt.ItemIsEnabled

        pkg = self._get_pkg(index)
        ans = QtCore.QAbstractTableModel.flags(self, index)
        if pkg and not pkg.installed:
            if index.column() == 2:
                ans |= QtCore.Qt.ItemIsUserCheckable
                ans |= QtCore.Qt.ItemIsEditable
                ans |= QtCore.Qt.ItemIsSelectable
        else:
            ans &= ~QtCore.Qt.ItemIsEnabled
        return ans

    def headerData(self, section, orientation, role):
        """
            Native optionnal function
            Returns the table's header infos
            :orientation:
                QtCore.Qt:Orientation
            :role:
                QtCore.Qt:Role
        """
        # Alignement
        if role == QtCore.Qt.TextAlignmentRole:
            if orientation == QtCore.Qt.Horizontal:
                return QtCore.QVariant(int(QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter))
            return QtCore.QVariant(int(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter))

        # Headers
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()
        if orientation == QtCore.Qt.Horizontal:
            ret_val = TABLE_HEADER[section]
            return QtCore.QVariant(ret_val)
        else:
            return QtCore.QVariant(int(section + 1))

    #Cache update and file
    def update(self):
        """
            Update our apt cache and our packages list
        """
        acquire = QAcquireProgress()
        self._init_cache()

        print("Connecting slots")
        for sign in (QtCore.SIGNAL('statusChanged'), QtCore.SIGNAL('statusStarted()'),
                                            QtCore.SIGNAL('statusFinished()'),):
            self.connect(acquire, sign, self._reemit(sign))
        self.connect(acquire, QtCore.SIGNAL('statusFinished()'), self._update_datas)
        self.cache.update(acquire)

    def _update_datas(self):
        """
            Refresh the table's datas when a update has been called
        """
        self.cache = Cache()
        self.packages = []
        self.to_install = []
        self._populate()

    def install(self):
        """
            Install a list of packages
            @packages : a list of packages' names
        """
        acquire = QAcquireProgress()
        #FIXME : Il y a encore deux trois trucs qui vont pas
        install = QInstallProgress()
        print("Connecting slots")
        for sign in (QtCore.SIGNAL('statusChanged'), QtCore.SIGNAL('statusStarted()'),
                                            QtCore.SIGNAL('statusFinished()'),):
            self.connect(acquire, sign, self._reemit(sign))
            self.connect(install, sign, self._reemit(sign))
        self.connect(install, QtCore.SIGNAL('statusFinished()'),
                     self._update_datas)
        self.cache.commit(acquire, install)

    def _reemit(self, signal):
        """
            Returns a _reemit func for the given signal
        """
        em = self.emit
        def emitter(*args, **kw):
            em(signal, *args, **kw)
        return emitter