NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

panelFreelanceProjects.py (12140B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\info\panels\panelFreelanceProjects.py
      2 import uthread2
      3 from carbonui import uiconst, TextColor
      4 from carbonui.text.styles import TextHeader
      5 from carbonui.control.contextMenu.menuData import MenuData
      6 from carbonui.primitives.container import Container
      7 from characterdata import careerpath
      8 from eve.client.script.ui.quickFilter import QuickFilterEdit
      9 from freelanceprojects.client import freelance_signals
     10 from freelanceprojects.client.api import get_freelance_projects_repository
     11 from freelanceprojects.client.ui.admin_browser import FreelanceFilterMenuButtonIcon, FreelanceSortByMenuButtonIcon
     12 from freelanceprojects.client.ui.admin_browser_settings import career_path_filter_setting, sort_by_setting, have_participated_in_filter_setting, have_unclaimed_rewards_for_filter_setting, only_my_active_jobs_setting, only_committable_jobs_setting
     13 from jobboard.client import ProviderType, get_provider
     14 from jobboard.client.features.freelance_projects.no_jobs_container import NoCorporationJobsContainer
     15 from jobboard.client.features.freelance_projects.provider_section import FreelanceJobProviderSection
     16 from localization import GetByLabel, GetByMessageID
     17 from logging import getLogger
     18 from threadutils import throttled
     19 logger = getLogger('freelance_projects')
     20 
     21 class PanelFreelanceProjects(Container):
     22 
     23     def ApplyAttributes(self, attributes):
     24         super(PanelFreelanceProjects, self).ApplyAttributes(attributes)
     25         self._activeTasklet = None
     26         self._corporation_id = attributes.corporation_id
     27         self._reconstruct_thread = None
     28         self._jobs_section = None
     29         self._viewer_id = attributes.viewer_id
     30         self.quick_filter = None
     31         self._repository = get_freelance_projects_repository()
     32         self._construct_top_container()
     33         self._connect_signals()
     34 
     35     def Close(self):
     36         self._repository.stopped_viewing(self._viewer_id, [self._corporation_id])
     37         self._disconnect_signals()
     38         super(PanelFreelanceProjects, self).Close()
     39 
     40     def _connect_signals(self):
     41         freelance_signals.on_storage_invalidated.connect(self._on_storage_invalidated)
     42         freelance_signals.on_repository_cleared.connect(self._on_repository_cleared)
     43         freelance_signals.on_created.connect(self._on_projects_changed)
     44         freelance_signals.on_closed.connect(self._on_projects_changed)
     45         freelance_signals.on_expired.connect(self._on_projects_changed)
     46         freelance_signals.on_completed.connect(self._on_projects_changed)
     47         freelance_signals.on_kicked.connect(self._on_projects_changed)
     48         career_path_filter_setting.on_change.connect(self._on_setting_changed)
     49         only_my_active_jobs_setting.on_change.connect(self._on_setting_changed)
     50         sort_by_setting.on_change.connect(self._on_setting_changed)
     51         have_participated_in_filter_setting.on_change.connect(self._on_setting_changed)
     52         have_unclaimed_rewards_for_filter_setting.on_change.connect(self._on_setting_changed)
     53         only_committable_jobs_setting.on_change.connect(self._on_setting_changed)
     54 
     55     def _disconnect_signals(self):
     56         freelance_signals.on_storage_invalidated.disconnect(self._on_storage_invalidated)
     57         freelance_signals.on_repository_cleared.disconnect(self._on_repository_cleared)
     58         freelance_signals.on_created.disconnect(self._on_projects_changed)
     59         freelance_signals.on_closed.disconnect(self._on_projects_changed)
     60         freelance_signals.on_expired.disconnect(self._on_projects_changed)
     61         freelance_signals.on_completed.disconnect(self._on_projects_changed)
     62         freelance_signals.on_kicked.disconnect(self._on_projects_changed)
     63         career_path_filter_setting.on_change.disconnect(self._on_setting_changed)
     64         only_my_active_jobs_setting.on_change.disconnect(self._on_setting_changed)
     65         sort_by_setting.on_change.disconnect(self._on_setting_changed)
     66         have_participated_in_filter_setting.on_change.disconnect(self._on_setting_changed)
     67         have_unclaimed_rewards_for_filter_setting.on_change.disconnect(self._on_setting_changed)
     68         only_committable_jobs_setting.on_change.disconnect(self._on_setting_changed)
     69 
     70     def _on_projects_changed(self, *args):
     71         self._reconstruct_content()
     72 
     73     def _on_setting_changed(self, *_args):
     74         self._reconstruct_content()
     75 
     76     @throttled(0.5)
     77     def _reconstruct_content(self):
     78         if not self.display:
     79             return
     80         self.Load()
     81 
     82     def _construct_top_container(self):
     83         self.top_container = Container(name='top_container', parent=self, align=uiconst.TOTOP, height=32, padTop=8, padBottom=8)
     84         TextHeader(name='title_label', parent=self.top_container, align=uiconst.TOLEFT, text=GetByLabel('UI/Corporations/FreelanceProjects/PanelTitle'), color=TextColor.HIGHLIGHT, padLeft=4, padRight=4, autoFadeSides=16)
     85         self.total_active_projects = TextHeader(name='title_label', parent=self.top_container, align=uiconst.TOLEFT, text=GetByLabel(labelNameAndPath='UI/Corporations/CorporationWindow/Politics/ExtraInfoWrapper', extraInfo='-'), color=TextColor.HIGHLIGHT, autoFadeSides=16)
     86         self._construct_filter()
     87         self._construct_sort()
     88 
     89     def Load(self):
     90         if self._reconstruct_thread and self._reconstruct_thread.is_alive():
     91             self._reconstruct_thread.kill()
     92         self._reconstruct_thread = uthread2.start_tasklet(self._load_projects)
     93 
     94     def _construct_filter(self):
     95         self.filter_button = FreelanceShowInfoFilterMenuButtonIcon(parent=self.top_container, align=uiconst.TORIGHT, padRight=8)
     96         self.quick_filter = QuickFilterEdit(parent=self.top_container, align=uiconst.TORIGHT, width=120)
     97         self.quick_filter.ReloadFunction = self._reconstruct_content
     98 
     99     def _construct_sort(self):
    100         self.sort_button = FreelanceSortByMenuButtonIcon(parent=self.top_container, align=uiconst.TORIGHT)
    101 
    102     def _load_projects(self):
    103         if self._jobs_section and not self._jobs_section.destroyed:
    104             self._jobs_section.Close()
    105         self._jobs_section = FreelanceJobProviderSection(parent=self, job_provider=get_provider(ProviderType.FREELANCE_PROJECTS), is_relevant=self._is_relevant, sort_jobs=self._sorting_and_filtering_function, corporation_id=self._corporation_id, on_loaded_callback=self._on_loaded, custom_empty_state_func=self._create_empty_state)
    106         self._repository.started_viewing(self._viewer_id, [self._corporation_id])
    107         self._repository.request_projects_for_corporation(self._corporation_id, wait=True)
    108         self._jobs_section.load()
    109 
    110     def _create_empty_state(self, parent):
    111         return NoCorporationJobsContainer(name='alert_container', parent=parent, align=uiconst.TOTOP, get_failures=self._get_failures, display=False)
    112 
    113     def _get_failures(self):
    114         storage_ids = self._get_storages()
    115         return self._repository.get_storage_failures(storage_ids)
    116 
    117     def _get_storages(self):
    118         storage_ids = {self._corporation_id}
    119         return storage_ids
    120 
    121     def _is_relevant(self, job):
    122         return job.corporation_id == self._corporation_id and job.is_active
    123 
    124     def _on_storage_invalidated(self, storage_id):
    125         if storage_id == self._corporation_id and self._jobs_section:
    126             self.Load()
    127 
    128     def _on_repository_cleared(self):
    129         self.Load()
    130 
    131     def _on_loaded(self):
    132         self.total_active_projects.text = GetByLabel('UI/Corporations/CorporationWindow/Politics/ExtraInfoWrapper', extraInfo=self._repository.get_amount_active_for_corporation(self._corporation_id))
    133 
    134     def _sorting_and_filtering_function(self, jobs):
    135         return self._get_projects_sorted(self._get_projects_filtered(jobs))
    136 
    137     def _get_projects_sorted(self, projects):
    138         sortBy = sort_by_setting.get()
    139         if sortBy == 'name':
    140             return sorted(projects, key=lambda project: project.title.lower())
    141         elif sortBy == 'name_reversed':
    142             return sorted(projects, key=lambda project: project.title.lower(), reverse=True)
    143         elif sortBy == 'date_created':
    144             return sorted(projects, key=lambda project: project.created_time)
    145         elif sortBy == 'date_created_reversed':
    146             return sorted(projects, key=lambda project: project.created_time, reverse=True)
    147         elif sortBy == 'progress':
    148             return sorted(projects, key=lambda project: project.progress_percentage)
    149         elif sortBy == 'progress_reversed':
    150             return sorted(projects, key=lambda project: project.progress_percentage, reverse=True)
    151         elif sortBy == 'num_jumps':
    152             return sorted(projects, key=lambda project: project.jumps)
    153         elif sortBy == 'num_jumps_reversed':
    154             return sorted(projects, key=lambda project: project.jumps, reverse=True)
    155         elif sortBy == 'time_remaining':
    156             return sorted(projects, key=lambda project: (project.expiration_time is None, project.expiration_time))
    157         elif sortBy == 'time_remaining_reversed':
    158             return sorted(projects, key=lambda project: (project.expiration_time is None, project.expiration_time), reverse=True)
    159         else:
    160             logger.warning(u'sort_by method not found: {}'.format(sortBy))
    161             return projects
    162 
    163     def _get_projects_filtered(self, projects):
    164         filterStr = self.quick_filter.GetValue()
    165         if filterStr:
    166             projects = [ project for project in projects if filterStr.lower() in project.title.lower() ]
    167         if have_participated_in_filter_setting.is_enabled():
    168             projects = [ project for project in projects if project.personal_progress ]
    169         if have_unclaimed_rewards_for_filter_setting.is_enabled():
    170             projects = [ project for project in projects if project.has_claimable_rewards ]
    171         if only_my_active_jobs_setting.is_enabled():
    172             projects = [ project for project in projects if project.is_committed ]
    173         if only_committable_jobs_setting.is_enabled():
    174             projects = [ project for project in projects if project.can_commit() ]
    175         career_path_filter = career_path_filter_setting.get()
    176         if career_path_filter is not None:
    177             projects = [ project for project in projects if project.career_path == career_path_filter ]
    178         return projects
    179 
    180 
    181 class FreelanceShowInfoFilterMenuButtonIcon(FreelanceFilterMenuButtonIcon):
    182 
    183     def ApplyAttributes(self, attributes):
    184         super(FreelanceShowInfoFilterMenuButtonIcon, self).ApplyAttributes(attributes)
    185         have_participated_in_filter_setting.on_change.connect(self._on_filter_changed)
    186         have_unclaimed_rewards_for_filter_setting.on_change.connect(self._on_filter_changed)
    187         only_my_active_jobs_setting.on_change.connect(self._on_filter_changed)
    188         only_committable_jobs_setting.on_change.connect(self._on_filter_changed)
    189 
    190     def _is_filter_active(self):
    191         return have_participated_in_filter_setting.is_enabled() or have_unclaimed_rewards_for_filter_setting.is_enabled() or career_path_filter_setting.get() is not None or only_my_active_jobs_setting.is_enabled() or only_committable_jobs_setting.is_enabled()
    192 
    193     def GetMenu(self):
    194         m = MenuData()
    195         m.AddCaption(self.hint)
    196         m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/OnlyMyActiveJobs'), setting=only_my_active_jobs_setting)
    197         m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/OnlyProjectsICanAccept'), setting=only_committable_jobs_setting)
    198         m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/FilterJobsIHaveContributedTo'), setting=have_participated_in_filter_setting)
    199         m.AddCheckbox(GetByLabel('UI/Corporations/FreelanceProjects/HaveUnclaimedRewardsFor'), setting=have_unclaimed_rewards_for_filter_setting)
    200         m.AddSeparator()
    201         m.AddCaption(GetByLabel('Character/CareerPaths/CareerPath'))
    202         m.AddRadioButton(GetByLabel('UI/Common/Any'), None, career_path_filter_setting)
    203         for c_id, c in careerpath.get_career_paths().iteritems():
    204             m.AddRadioButton(GetByMessageID(c.nameID), c_id, career_path_filter_setting)
    205 
    206         return m