Example #1
0
 def handle_response(self, oDialog):
     """Handle the response from the config dialog"""
     iResponse = oDialog.run()
     if iResponse == Gtk.ResponseType.OK:
         oFile, bDir, bDownload, bDownloadExpansions = oDialog.get_data()
         if bDir:
             # New directory
             if self._accept_path(oFile):
                 # Update preferences
                 self.image_frame.update_config_path(oFile)
                 self._activate_menu()
         elif oFile:
             if self._unzip_file(oFile):
                 self._activate_menu()
             else:
                 do_complaint_error('Unable to successfully unzip data')
             oFile.close()  # clean up temp file
         else:
             # Unable to get data
             do_complaint_error('Unable to configure card images plugin')
         # Update download option
         self.set_config_item(DOWNLOAD_IMAGES, bDownload)
         self.set_config_item(DOWNLOAD_EXPANSIONS, bDownloadExpansions)
         # Reset expansions settings if needed
         self.image_frame.check_images()
     # get rid of the dialog
     oDialog.destroy()
    def _get_cards(self):
        """Extract card details from the card set."""
        oCryptFilter = CryptCardFilter()

        self.aCrypt = get_cards_filter(self.model, oCryptFilter)
        self.aLibrary = get_cards_filter(self.model, FilterNot(oCryptFilter))

        if len(self.aLibrary) < 7:
            do_complaint_error('Library needs to be at least as large as the'
                               ' opening hand')
            return False

        if len(self.aCrypt) < 4:
            do_complaint_error('Crypt needs to be at least as large as the'
                               ' opening draw')
            return False

        for sType in MultiCardTypeFilter.get_values():
            aList = get_cards_filter(self.model, CardTypeFilter(sType))
            if aList and aList[0] in self.aLibrary:
                self.dCardTypes[sType] = set([oC.name for oC in aList])

        for sFunction in CardFunctionFilter.get_values():
            aList = get_cards_filter(self.model, CardFunctionFilter(sFunction))
            if aList:
                self.dCardProperties[sFunction] = set([oC.name for oC in
                                                       aList])
        return True
 def post_set_card_text(self, _sSignal, oPhysCard):
     """Update the card text pane with the 'show merged', etc. buttons"""
     self._oAbsCard = oPhysCard.abstractCard
     self._oFakeCard = None
     if self._oAbsCard.level is None:
         if self._oAbsCard not in self._aBaseVamps:
             return
     if self._oAbsCard in self._aExcluded:
         return
     try:
         self._oFakeCard = FakeCard(self._oAbsCard, self._dReplaceMap)
     except SQLObjectNotFound as oExc:
         do_complaint_error("Unable to created merged vampire for %s" %
                            self._oAbsCard.name)
         self._aExcluded.add(self._oAbsCard)
         logging.warning("Merged vampire creation failed (%s).",
                         oExc,
                         exc_info=1)
         return
     oCardTextView = self.parent.card_text_pane.view
     # Button logic
     # For the normal view, we show the buttons
     # "Merged" and "Other version" (Base / Advanced)
     # Because of how add_button_to_text is implemented, we
     # add the second button first
     if self._oAbsCard.level is None:
         oCardTextView.add_button_to_text(self._oAdv, "  ")
     else:
         oCardTextView.add_button_to_text(self._oBase, "  ")
     oCardTextView.add_button_to_text(self._oMerged, "\n  ")
    def activate(self, _oWidget):
        """Generate the PDF file"""
        oPrintOp = Gtk.PrintOperation()
        if self._oSettings:
            oPrintOp.set_print_settings(self._oSettings)

        oPrintOp.connect("begin-print", self.begin_print)
        oPrintOp.connect("end-print", self.end_print)
        oPrintOp.connect("draw-page", self.draw_page)
        oPrintOp.set_custom_tab_label('Proxy Set Print Settings')

        dCustomData = {}
        oPrintOp.connect('create-custom-widget', self._add_print_widgets,
                         dCustomData)
        oPrintOp.connect('custom-widget-apply', self._get_print_widgets,
                         dCustomData)

        oRes = oPrintOp.run(Gtk.PrintOperationAction.PRINT_DIALOG, self.parent)
        if self._aMissing:
            # We aborted due to missing cards
            aErrors = [
                "Error printing card set.",
                "Unable to load images for the following cards:"
            ]
            aErrors.extend(sorted(self._aMissing))
            sErr = '\n'.join(aErrors)
            do_complaint_error(sErr)
        elif oRes == Gtk.PrintOperationResult.ERROR:
            do_complaint_error("Error printing card set:\n" +
                               oPrintOp.get_error())
        elif oRes == Gtk.PrintOperationResult.APPLY:
            self._oSettings = oPrintOp.get_print_settings()
 def do_update(self):
     """Handle the 'download stuff' respone from the startup check"""
     sPrefsValue = self.get_config_item('twda configured')
     if sPrefsValue.lower() != 'yes':
         return
     aUrls, aDates, aHashes = find_all_data_packs(
         'twd', fErrorHandler=gui_error_handler)
     if not self._get_decks(aUrls, aDates, aHashes):
         do_complaint_error("Didn't find any TWD data to download")
    def find_twda(self, _oWidget, sMode):
        """Find decks which match the given search"""
        # Only want the distinct cards - numbers are unimportant
        aAbsCards = set(self._get_selected_abs_cards())
        if not aAbsCards:
            do_complaint_error('Need to select some cards for this plugin')
            return
        if len(aAbsCards) > 20:
            do_complaint_error('Too many cards selected (%d). Please select '
                               'no more than 20 cards' % len(aAbsCards))
            return
        aCardFilters = []
        iTotCards = len(aAbsCards)
        for oCard in aAbsCards:
            aCardFilters.append(SpecificCardFilter(oCard))
        # needs to be OR, since we're matching against the card to card set
        # mapping table
        oCardFilter = FilterOrBox(aCardFilters)
        aNames = self._get_twda_names()
        oMapFilter = MultiPhysicalCardSetMapFilter(aNames)
        oFullFilter = FilterAndBox([oCardFilter, oMapFilter])

        # pylint: disable=no-member
        # SQLObject confuses pylint
        dCardSets = {}
        for oMapCard in oFullFilter.select(MapPhysicalCardToPhysicalCardSet):
            oCS = oMapCard.physicalCardSet
            sCardName = IAbstractCard(oMapCard).name
            dCardSets.setdefault(oCS, {})
            dCardSets[oCS].setdefault(sCardName, 0)
            dCardSets[oCS][sCardName] += 1

        if sMode == 'all' and iTotCards > 1:
            # This is a little clunky, but, because of how we construct the
            # filters, we currently have the any match set, so we need to
            # filter this down to those that match all the cards
            for oCS in list(dCardSets):
                if len(dCardSets[oCS]) != iTotCards:
                    # Not all, so drop this one
                    del dCardSets[oCS]

        sCards = '",  "'.join(sorted([x.name for x in aAbsCards]))
        if sMode == 'any':
            sMatchText = 'Matching ANY of "%s"' % sCards
        else:
            sMatchText = 'Matching ALL of "%s"' % sCards

        # Create a dialog showing the results
        if dCardSets:
            oDlg = self._fill_dlg(dCardSets, sMatchText)
        else:
            oDlg = self._empty_dlg(sMatchText)

        oDlg.set_default_size(700, 600)
        oDlg.show_all()
        oDlg.show()
    def _get_decks(self, aUrls, aDates, aHashes):
        """Unzip a file containing the decks."""
        aZipHolders = []
        aToUnzip, aToReplace = self._get_decks_to_download(aUrls, aDates,
                                                           aHashes)
        if not aToUnzip:
            return False
        # We download everything first, so we don't delete card sets which
        # fail to download.
        oBinLogHandler = BinnedCountLogHandler()
        oProgressDialog = ProgressDialog()
        oProgressDialog.set_description("Downloading TWDA data")
        oLogger = Logger('Download zip files')
        oLogger.addHandler(oBinLogHandler)
        oBinLogHandler.set_dialog(oProgressDialog)
        oBinLogHandler.set_tot_bins(len(aToUnzip))
        oProgressDialog.show()
        # We sort the list of urls to download for cosmetic reasons
        for sUrl, sTWDA, sHash in sorted(aToUnzip, key=lambda x: x[1]):
            oFile = urlopen_with_timeout(sUrl,
                                         fErrorHandler=gui_error_handler,
                                         bBinary=True)
            oProgressDialog.set_description('Downloading %s' % sTWDA)
            try:

                sData = fetch_data(oFile, sHash=sHash,
                                   oLogHandler=oBinLogHandler,
                                   fErrorHandler=gui_error_handler)
            except HashError:
                do_complaint_error("Checksum failed for %s\nSkipping"
                                   % sTWDA)
                # Don't delete this, since we're not replacing it
                aToReplace.remove(sTWDA)
                continue
            oZipFile = ZipFileWrapper(BytesIO(sData))
            aZipHolders.append(oZipFile)
            oBinLogHandler.inc_cur_bin()
        oProgressDialog.destroy()

        # Bomb out if we're going to end up doing nothing
        if not aZipHolders:
            return False

        # Delete all TWDA entries in the holders we replace
        # We do this to handle card sets being removed from the TWDA
        # correctly
        aToDelete = []
        for oCS in list(PhysicalCardSet.select()):
            if not oCS.parent:
                continue
            if oCS.parent.name in aToReplace:
                aToDelete.append(oCS.name)

        return unzip_files_into_db(aZipHolders, "Adding TWDA Data",
                                   self.parent, aToDelete)
Example #8
0
 def handle_response(self, sFilename):
     """Actually do the export"""
     if sFilename is None:
         return
     oCardSet = self._get_card_set()
     if not oCardSet:
         return
     dDeck = json.loads(DECK_TEMPLATE)
     aCrypt = []
     aLibrary = []
     for oCard in oCardSet.cards:
         # Need to turn name into the JSON file version
         sJSONName = make_json_name(oCard.abstractCard)
         sAltName = make_alternative_json_name(oCard.abstractCard)
         if sJSONName not in self._dTTSData:
             # Check if it's just using the card name instead
             if sAltName not in self._dTTSData:
                 do_complaint_error("Unable to find an entry for %s (%s)" %
                                    (oCard.abstractCard.name, sJSONName))
                 logging.warning("Unable to find an entry for %s (%s)",
                                 oCard.abstractCard.name, sJSONName)
                 return
             sJSONName = sAltName
         if is_crypt_card(oCard.abstractCard):
             aCrypt.append(sJSONName)
         else:
             aLibrary.append(sJSONName)
     dCrypt = dDeck['ObjectStates'][0]
     dLibrary = dDeck['ObjectStates'][1]
     for sName in sorted(aCrypt):
         oObj = self._dTTSData[sName]
         dTTSCard = oObj.copy()
         dTTSCard['Transform'] = CRYPT_TRANSFORM
         dCrypt['DeckIDs'].append(dTTSCard['CardID'])
         dCrypt['CustomDeck'].update(dTTSCard['CustomDeck'])
         dCrypt['ContainedObjects'].append(dTTSCard)
     for sName in sorted(aLibrary):
         oObj = self._dTTSData[sName]
         dTTSCard = oObj.copy()
         dTTSCard['Transform'] = LIB_TRANSFORM
         dLibrary['DeckIDs'].append(dTTSCard['CardID'])
         dLibrary['CustomDeck'].update(dTTSCard['CustomDeck'])
         dLibrary['ContainedObjects'].append(dTTSCard)
     with open(sFilename, 'w') as oFile:
         json.dump(dDeck, oFile, indent=2)
 def handle_response(self, oDialog):
     """Handle the response from the config dialog"""
     iResponse = oDialog.run()
     if iResponse == Gtk.ResponseType.OK:
         sData = oDialog.get_data()
         (bExcludeStoryDecks, bExcludeDemoDecks) = \
             oDialog.get_excluded_decks()
         if not sData:
             do_complaint_error('Unable to access zipfile data')
         elif not self._unzip_file(sData, bExcludeStoryDecks,
                                   bExcludeDemoDecks):
             do_complaint_error('Unable to successfully unzip zipfile')
     if self.check_enabled():
         self.oToggle.set_sensitive(True)
     else:
         self.oToggle.set_sensitive(False)
     # cleanup
     oDialog.destroy()
 def _make_cs(self, _oButton, oDlg):
     """Create a card set with the given cards"""
     # pylint: disable=no-member
     # SQLObject confuses pylint
     oView = oDlg.get_cur_widget().get_child()
     aCards = oView.get_selected_cards()
     if not aCards:
         do_complaint_error("No cards selected for card set.")
         return
     sCSName = create_card_set(self.parent)
     if sCSName:
         oCardSet = IPhysicalCardSet(sCSName)
         for oCard in aCards:
             # We add with unknown expansion
             # pylint: disable=no-member
             # SQLObject confuses pylint
             oCardSet.addPhysicalCard(IPhysicalCard((oCard, None)))
         self._open_cs(sCSName, True)
    def do_update(self):
        """Download the starter decks, if requested."""
        sPrefsValue = self.get_config_item('show starters')
        # Only check if we're meant to show the starters
        if sPrefsValue.lower() != 'yes':
            return
        aUrls, aDates, aHashes = find_all_data_packs(
            'starters', fErrorHandler=gui_error_handler)

        if self._check_for_starters_to_download(aUrls[0], aDates[0]):
            # Check to see if cards are available
            bExcludeDemoDecks = False
            bExcludeStorylineDecks = False
            try:
                _oSkip = IRarityPair(('White Wolf 2003 Demo', 'Demo'))
            except SQLObjectNotFound:
                bExcludeDemoDecks = True
            try:
                _oSkip = IRarityPair(('Nergal Storyline', 'Storyline'))
            except SQLObjectNotFound:
                bExcludeStorylineDecks = True
            oHolder = find_holder(STARTER_HOLDERS)
            if oHolder:
                # We assume missing Holders are due to user choice, so we
                # try to honour those. People can always use the explicit
                # download option to recover accidental deletions
                if not bExcludeDemoDecks:
                    bExcludeDemoDecks = find_holder(DEMO_HOLDERS) is None
                if not bExcludeStorylineDecks:
                    bExcludeStorylineDecks = \
                        find_holder(STORYLINE_HOLDERS) is None
            oFile = urlopen_with_timeout(aUrls[0],
                                         fErrorHandler=gui_error_handler,
                                         bBinary=True)
            if oFile:
                sData = progress_fetch_data(oFile, None, aHashes[0])
            else:
                sData = None
            if not sData:
                do_complaint_error('Unable to access zipfile data')
            elif not self._unzip_file(sData, bExcludeStorylineDecks,
                                      bExcludeDemoDecks):
                do_complaint_error('Unable to successfully unzip zipfile')
Example #12
0
 def _check_selection(self, aSelectedCards):
     """Check that selection is useable."""
     bCrypt = False
     bLibrary = False
     for oCard in aSelectedCards:
         # pylint: disable=simplifiable-if-statement
         # pylint misidentifies this because it misses the loop
         if is_crypt_card(oCard):
             bCrypt = True
         else:
             bLibrary = True
     # Check that selection doesn't mix crypt and libraries
     if bLibrary and bCrypt:
         do_complaint_error("Can't operate on selections including both"
                            " Crypt and Library cards")
         return False
     # Store this for later queries
     self.bCrypt = bCrypt
     return True
Example #13
0
    def _make_pcs_from_cluster(self, iClusterId):
        """Create a Card Set from the chosen cluster"""
        sDeckName = '_cluster_deck_%d' % (iClusterId, )

        # Check Deck Doesn't Exist
        if check_cs_exists(sDeckName):
            do_complaint_error("Card Set %s already exists." % sDeckName)
            return

        # Create Deck
        oDeck = PhysicalCardSet(name=sDeckName)

        # pylint: disable=no-member
        # SQLObject confuses pylint
        aCards = [
            IPhysicalCard(self._aCards[x]) for x in self._aClusters[iClusterId]
        ]
        self._commit_cards(oDeck, aCards)
        self._open_cs(sDeckName, True)
Example #14
0
 def handle_response(self, oDialog):
     """Handle running and responding to the download dialog"""
     iResponse = oDialog.run()
     if iResponse == Gtk.ResponseType.OK:
         if oDialog.is_url():
             aUrls, aDates, aHashes = oDialog.get_url_data()
             if not aUrls:
                 do_complaint_error('Unable to access TWD data')
             elif not self._get_decks(aUrls, aDates, aHashes):
                 do_complaint_error(
                     "Didn't find any TWD data to download")
             else:
                 # Successful download, so we're configured
                 self.set_config_item('twda configured', 'Yes')
         else:
             if self._unzip_twda_file(oDialog.get_file_data()):
                 # Success, so we're configured
                 self.set_config_item('twda configured', 'Yes')
     # cleanup
     oDialog.destroy()
    def activate(self, _oWidget):
        """Create the dialog.

           Prompt the user for attributes that are important and so forth
           """
        self.oSelCard = self._get_selected_crypt_card()
        if not self.oSelCard:
            do_complaint_error("Please select only 1 crypt card.")
            return
        # We treat imbued and vampires differently
        # pylint: disable=no-member
        # SQLObject confuses pylint
        if is_vampire(self.oSelCard):
            if not self.oSelCard.discipline:
                do_complaint_error("Please select a vampire with disciplines.")
                return
            dGroups = self.find_vampires_like()
        else:
            if not self.oSelCard.virtue:
                do_complaint_error("Please select an Imbued with virtues.")
                return
            dGroups = self.find_imbued_like()
        if dGroups:
            self.display_results(dGroups)
Example #16
0
 def _complain_size(self):
     """Correct complaint about the number of cards."""
     if self.bCrypt:
         do_complaint_error("Crypt must be larger than the opening draw")
     else:
         do_complaint_error("Library must be larger than the opening hand")