def card(self, _id): query = QtSql.QSqlQuery("""select _fact_id, card_type_id, fact_view_id, extra_data from cards where _id=%d""" % (_id, )) query.first() fact = self.fact(query.value(0)) # Note that for the card type, we turn to the component manager as # opposed to this database, as we would otherwise miss the built-in # system card types card_type = self.card_type_with_id(query.value(1)) fact_view_id = query.value(2) for fact_view in card_type.fact_views: if fact_view.id == fact_view_id: card = Card(card_type, fact, fact_view) # We need extra_data to display the cloze cards. extra_data = query.value(3) if extra_data == "": card.extra_data = {} else: card.extra_data = eval(extra_data) break # Let's not add tags to speed things up, they don't affect the card # browser renderer #query = QtSql.QSqlQuery("""select _tag_id from tags_for_card # where _card_id=%d""" % (_id, )) #query.next() #while query.isValid(): # card.tags.add(self.tag(query.value(0))) # query.next() return card
def card(self, _id): query = QtSql.QSqlQuery("""select _fact_id, card_type_id, fact_view_id, extra_data from cards where _id=%d""" % (_id, )) query.first() fact = self.fact(query.value(0).toInt()[0]) # Note that for the card type, we turn to the component manager as # opposed to this database, as we would otherwise miss the built-in # system card types card_type = self.card_type_with_id(unicode(query.value(1).toString())) fact_view_id = unicode(query.value(2).toString()) for fact_view in card_type.fact_views: if fact_view.id == fact_view_id: card = Card(card_type, fact, fact_view) # We need extra_data to display the cloze cards. extra_data = unicode(query.value(3).toString()) if extra_data == "": card.extra_data = {} else: card.extra_data = eval(extra_data) break # Let's not add tags to speed things up, they don't affect the card # browser renderer #query = QtSql.QSqlQuery("""select _tag_id from tags_for_card # where _card_id=%d""" % (_id, )) #query.next() #while query.isValid(): # card.tags.add(self.tag(query.value(0).toInt()[0])) # query.next() return card
def card_from_log_entry(self, log_entry): # We should not receive cards with question and answer data, only # cards based on facts. if "f" in log_entry: raise AttributeError # Get card object to be deleted now. if log_entry["type"] == EventTypes.DELETED_CARD: try: return self.card(log_entry["o_id"], is_id_internal=False) except MnemosyneError: # There is no fact in the database. # We have created and deleted this card since the last sync, # so we just return an empty shell. card_type = self.card_type_with_id("1") fact = Fact({"f": "f", "b": "b"}, id="") card = Card(card_type, fact, card_type.fact_views[0], creation_time=0) card._id = None # Signals special case to 'delete_card'. card.id = log_entry["o_id"] return card # Create an empty shell of card object that will be deleted later # during this sync. if "tags" not in log_entry: card_type = self.card_type_with_id("1") fact = Fact({"f": "f", "b": "b"}, id="") card = Card(card_type, fact, card_type.fact_views[0], creation_time=0) card.id = log_entry["o_id"] return card # Create card object. if "card_t" not in log_entry: # Client only supports simple cards. card_type = self.card_type_with_id("1") else: if log_entry["card_t"] not in \ self.component_manager.card_type_with_id: # If the card type is not in the database, it's possible that # the data for this card type will follow later during the # sync. In that case, create a dummy card type here, which # will be corrected by a later edit event. Hovewer, we still # need to instantiate this card type later, so that we can # catch errors, e.g. due to bad plugins. try: self.activate_plugins_for_card_type_with_id\ (log_entry["card_t"]) card_type = self.card_type_with_id\ (log_entry["card_t"]) except: self.card_types_to_instantiate_later.add(\ log_entry["card_t"]) card_type = self.card_type_with_id("1") log_entry["fact_v"] = card_type.fact_views[0].id else: card_type = self.card_type_with_id(log_entry["card_t"]) fact = self.fact(log_entry["fact"], is_id_internal=False) # When importing, set the creation time to the current time. if self.importing and not self.importing_with_learning_data: log_entry["c_time"] = int(time.time()) log_entry["m_time"] = int(time.time()) for fact_view in card_type.fact_views: if fact_view.id == log_entry["fact_v"]: card = Card(card_type, fact, fact_view, creation_time=log_entry["c_time"]) break for tag_id in log_entry["tags"].split(","): if self.has_tag_with_id(tag_id): card.tags.add(self.tag(tag_id, is_id_internal=False)) else: # The tag has been deleted later later during the log. Don't # worry about it now, this will be corrected by a later # EDITED_CARD event. pass if self.importing: if len(self.extra_tags_on_import) != 0: card.tags.discard(\ self.tag("__UNTAGGED__", is_id_internal=False)) for tag in self.extra_tags_on_import: card.tags.add(tag) # Construct rest of card. The 'active' property does not need to be # handled here, as default criterion will be applied to the card # in the database functions. card.id = log_entry["o_id"] if (log_entry["type"] != EventTypes.ADDED_CARD) or self.importing: if self.has_card_with_id(card.id): card._id = self.con.execute("select _id from cards where id=?", (card.id, )).fetchone()[0] else: # Importing a card for the first time, so it is not yet in the # database. pass card.modification_time = log_entry["m_time"] card.grade = log_entry["gr"] card.easiness = log_entry["e"] card.acq_reps = log_entry["ac_rp"] card.ret_reps = log_entry["rt_rp"] card.lapses = log_entry["lps"] card.acq_reps_since_lapse = log_entry["ac_rp_l"] card.ret_reps_since_lapse = log_entry["rt_rp_l"] card.last_rep = log_entry["l_rp"] card.next_rep = log_entry["n_rp"] if "sch_data" in log_entry: card.scheduler_data = log_entry["sch_data"] if "extra" in log_entry: card.extra_data = eval(log_entry["extra"]) return card
def card_from_log_entry(self, log_entry): # We should not receive cards with question and answer data, only # cards based on facts. if "q" in log_entry: raise AttributeError # Get card object to be deleted now. if log_entry["type"] == EventTypes.DELETED_CARD: try: # More future-proof version of code in the except statement. # However, this will fail if after the last sync the other # partner created and deleted this card, so that there is no # fact information. return self.get_card(log_entry["o_id"], id_is_internal=False) except TypeError: # Less future-proof version which just returns an empty shell. # Make sure to set _id, though, as that will be used in # actually deleting the card. sql_res = self.con.execute("select * from cards where id=?", (log_entry["o_id"], )).fetchone() card_type = self.card_type_by_id("1") fact = Fact({}, card_type, creation_time=0, id="") card = Card(fact, card_type.fact_views[0]) card._id = sql_res["_id"] return card # Create an empty shell of card object that will be deleted later # during this sync. if "tags" not in log_entry: card_type = self.card_type_by_id("1") fact = Fact({}, card_type, creation_time=0, id="") card = Card(fact, card_type.fact_views[0]) card.id = log_entry["o_id"] return card # Create card object. fact = self.get_fact(log_entry["fact"], id_is_internal=False) for fact_view in fact.card_type.fact_views: if fact_view.id == log_entry["fact_v"]: card = Card(fact, fact_view) break for tag_id in log_entry["tags"].split(","): try: card.tags.add(self.get_tag(tag_id, id_is_internal=False)) except TypeError: # The tag has been later later during the log. Don't worry # about it now, this will be corrected by a later # UPDATED_CARD event. pass card.id = log_entry["o_id"] if log_entry["type"] != EventTypes.ADDED_CARD: card._id = self.con.execute("select _id from cards where id=?", (card.id, )).fetchone()[0] card.active = True card.grade = log_entry["gr"] card.easiness = log_entry["e"] card.acq_reps = log_entry["ac_rp"] card.ret_reps = log_entry["rt_rp"] card.lapses = log_entry["lps"] card.acq_reps_since_lapse = log_entry["ac_rp_l"] card.ret_reps_since_lapse = log_entry["rt_rp_l"] card.last_rep = log_entry["l_rp"] card.next_rep = log_entry["n_rp"] if "sch_data" in log_entry: card.scheduler_data = log_entry["sch_data"] if "extra" in log_entry: card.extra_data = eval(log_entry["extra"]) return card