Example #1
0
class MainWidget(QtGui.QWidget):
    """The main tab, featuring the KiKrit client GUI.

	"""

    # Widhgets:
    search_line = None
    merchandise_list = None
    stack = None
    order_page = None
    balance_page = None
    add_button = None
    remove_button = None
    msg = None

    # Keyboard shortcuts:
    ks_left = None
    ks_right = None
    ks_enter = None
    ks_escape = None
    ks_f5 = None
    ks_alphanum = None

    def __init__(self, rfid_thread, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.rfid_thread = rfid_thread

        # Views:
        self.search_line = SearchLine(self)
        # self.search_line.grabKeyboard()

        self.merchandise_list = QtGui.QListView(self)
        self.merchandise_list.setModel(MerchandiseListModel(self._getItems(), self))
        self.merchandise_list.setSelectionMode(QtGui.QListView.SingleSelection)

        self.stack = QtGui.QStackedWidget()
        self.order_page = OrderPage(self.stack)
        self.balance_page = BalancePage(self.stack)
        self.stack.insertWidget(0, self.order_page)
        self.stack.insertWidget(1, self.balance_page)

        self.add_button = QtGui.QPushButton("Add", self)
        self.remove_button = QtGui.QPushButton("Remove", self)

        self.msg = MessageLine()

        # Keyboard shortcuts:
        self.ks_up = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Up", "Item|prev")), self)
        self.ks_down = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Down", "Item|next")), self)
        self.ks_left = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Left", "Select|left")), self)
        self.ks_right = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Right", "Select|right")), self)
        self.ks_return = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Return", "Item|add/remove")), self)
        self.ks_escape = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Escape", "Cancel current action")), self)
        self.ks_f5 = QtGui.QShortcut(QtGui.QKeySequence(self.tr("F5", "Force refresh")), self)
        self.ks_ctrls = QtGui.QShortcut(QtGui.QKeySequence(self.tr("Ctrl+s", "Focus search line")), self)

        # Layout:
        grid = QtGui.QGridLayout(self)
        grid.addWidget(self.search_line, 0, 0)
        grid.addWidget(self.merchandise_list, 1, 0)
        grid.addWidget(self.add_button, 2, 0)
        grid.addWidget(self.stack, 1, 1, 1, 1)
        grid.addWidget(self.remove_button, 2, 1)
        grid.addWidget(self.msg, 0, 1)

        self.setLayout(grid)

        # Connect signals:
        if parent != None:
            self.parentWidget().currentChanged.connect(self.tabChanged)

        self.search_line.textChanged.connect(self.searchLineChanged)
        self.ks_right.activated.connect(self.rightPressed)
        self.ks_left.activated.connect(self.leftPressed)
        self.ks_up.activated.connect(self.upPressed)
        self.ks_down.activated.connect(self.downPressed)
        self.ks_return.activated.connect(self.returnPressed)
        self.ks_escape.activated.connect(self.escapePressed)
        self.ks_f5.activated.connect(self.f5Pressed)
        self.ks_ctrls.activated.connect(self.activateSearchLine)

        self.add_button.clicked.connect(self.addClicked)
        self.remove_button.clicked.connect(self.removeClicked)
        self.rfid_thread.rfid_signal.connect(self.rfidEvent)

    def _reset(self):
        if self.stack.currentWidget() != self.order_page:
            self.stack.setCurrentWidget(self.order_page)
        self.order_page.emptyList()
        self.search_line.setText("")
        self.activateSearchLine()

    def _tabHasFocus(self):
        """Returns true if self is the parrents current widget, or if there is
		no parent.

		"""
        parent = self.parentWidget()
        if parent == None or parent.currentWidget() == self:
            return True
        return False

    def _getItems(self):
        """ Queries the database for all Merchandise objects, and return them
		as one large list.

		"""
        return list(Merchandise.objects.all())

    def _setSelected(self, list_view, new_index=None, next=False):
        """Takes a QListView object, and int and a bool. Changes selection to
		new_index, or to prev or next item in list view.

		"""
        # Get new_index:
        if new_index == None:
            if next:
                indexes = [i.row() + 1 for i in list_view.selectedIndexes()]
                if len(indexes) == 0:
                    indexes = [0]
            else:
                indexes = [i.row() - 1 for i in list_view.selectedIndexes()]
                if len(indexes) == 0:
                    indexes = [-1]
            new_index = indexes[0]

            # Check range:
        row_count = list_view.model().rowCount()
        if new_index < 0:
            new_index += row_count
        elif new_index >= row_count:
            new_index -= row_count

            # Update selection:
        mdl_index = list_view.model().index(new_index, 0)
        list_view.selectionModel().select(mdl_index, QtGui.QItemSelectionModel.ClearAndSelect)
        list_view.scrollTo(mdl_index)

    def tabChanged(self, index):
        if self.parentWidget().widget(index) == self:
            # self.search_line.grabKeyboard()
            self.f5Pressed()  # Re-read merchandise from db.
        else:
            # self.search_line.releaseKeyboard()
            pass

    def addClicked(self):
        """Called when the user presses the add-button"""
        # Set stack index:
        if self.stack.currentIndex() != 0:
            self.stack.setCurrentIndex(0)

        indexes = self.merchandise_list.selectedIndexes()

        if len(indexes) > 0:
            # Add items to order_page:
            mdl = self.merchandise_list.model()
            sel = [mdl.items[i.row()] for i in indexes]
            self.order_page.addItems(sel)
        self.activateSearchLine()

    def activateSearchLine(self):
        self.search_line.setFocus()
        self.search_line.selectAll()

    def removeClicked(self):
        """Called when the user presses the remove-button"""
        indexes = self.order_page.list_view.selectedIndexes()

        if len(indexes) > 0:
            # Remove items from order_page:
            sel = self.order_page.items(indexes)
            self.order_page.removeItems(sel)

            # Reset selection:
            self.order_page.list_view.selectionModel().select(indexes[0], QtGui.QItemSelectionModel.ClearAndSelect)

    def searchLineChanged(self, filter_str):
        self.merchandise_list.model().filter(filter_str)
        self._setSelected(self.merchandise_list, new_index=0)

    def leftPressed(self):
        self.merchandise_list.setFocus()

    def rightPressed(self):
        self.order_page.list_view.setFocus()

    def upPressed(self):
        if self.order_page.list_view.hasFocus():
            self._setSelected(self.order_page.list_view, next=False)
        else:
            self.merchandise_list.setFocus()
            self._setSelected(self.merchandise_list, next=False)

    def downPressed(self):
        if self.order_page.list_view.hasFocus():
            self._setSelected(self.order_page.list_view, next=True)
        else:
            self.merchandise_list.setFocus()
            self._setSelected(self.merchandise_list, next=True)

    def returnPressed(self):
        if self.order_page.list_view.hasFocus():
            self.removeClicked()
        else:
            self.addClicked()

    def escapePressed(self):
        if len(self.order_page.items()) > 0:
            self.msg.post("Order canceled", self.msg.STYLE_CANCEL)
        self._reset()

    def f5Pressed(self):
        indexes = self.merchandise_list.selectedIndexes()
        self.merchandise_list.model().setAllData(self._getItems())
        self.merchandise_list.model().filter(u"")
        filter_str = self.search_line.text()
        self.merchandise_list.model().filter(filter_str)

        # Reset selection:
        try:
            self.merchandise_list.selectionModel().select(indexes[0], QtGui.QItemSelectionModel.ClearAndSelect)
        except IndexError:
            pass

    def rfidEvent(self, rfid_str):
        # GUARD: tab has focus?
        if not self._tabHasFocus():
            return

            # Get account:
        try:
            card = RFIDCard.objects.get(rfid_string=unicode(rfid_str))
            account = card.account
        except RFIDCard.DoesNotExist:
            self.msg.post(u"RFID card not found", self.msg.STYLE_ERROR)
            account = None

            # Execute purchase:
        if account != None:
            items = self.order_page.items()

            if len(items) == 0:
                pass
            elif buy_merchandise(account, items):
                self._reset()
                color = account.COLOR_CHOICES[account.get_color()][1]
                self.msg.post(u"A successfull purchase mr. %s" % color, self.msg.STYLE_PURCHASE)
            else:
                color = account.COLOR_CHOICES[account.get_color()][1]
                self.msg.post(u"Transaction was dissalowed mr. %s" % color, self.msg.STYLE_ERROR)

            self.balance_page.showPage(account)