def __init__(self): ''' 一些初始设置 ''' super().__init__() self.m_pModel = ListModel() self.setModel(self.m_pModel)
def __init__(self, username, client_id, client_secret, redirect_url,user): super(SpotipyModule, self).__init__() # initalizes variables self.username = username self.client_id = client_id self.client_secret = client_secret self.redirect_url = redirect_url self.scope = 'user-library-read user-read-playback-state streaming' \ ' playlist-modify-public user-modify-playback-state playlist-modify-private ' \ 'user-read-playback-position user-read-currently-playing user-read-private' self.user = user self.spellchecker = spellchecker.SpellChecker(language=u'en', distance=2) self.queue_id = None self.playing = False self.queue_uri = None self.queue_changed = False self.current_queue = None self.playlist_ids = None self.playlist_names = None self.search_results = None self.dur_time = 0 self.artist = "" self.title = "" self.picture = qtc.QUrl() self.search_list = ListModel(SpotipyModule.SongWrapper) self.token = self.generate_token() self.queue = self.generate_queue() self.devices = self.token.devices()
class Backlinks(Gramplet): """ Displays the back references for an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ top = gtk.TreeView() titles = [ (_('Type'), 1, 100), (_('Name'), 2, 100), ('', 3, 1), #hidden column for the handle ('', 4, 1) ] #hidden column for non-localized object type self.model = ListModel(top, titles, event_func=self.cb_double_click) return top def display_backlinks(self, active_handle): """ Display the back references for an object. """ for classname, handle in \ self.dbstate.db.find_backlink_handles(active_handle): name = navigation_label(self.dbstate.db, classname, handle)[0] self.model.add((_(classname), name, handle, classname)) self.set_has_data(self.model.count > 0) def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle is None: return False for handle in self.dbstate.db.find_backlink_handles(active_handle): return True return False def cb_double_click(self, treeview): """ Handle double click on treeview. """ (model, iter_) = treeview.get_selection().get_selected() if not iter_: return (objclass, handle) = (model.get_value(iter_, 3), model.get_value(iter_, 2)) edit_object(self.dbstate, self.uistate, objclass, handle)
def _create_dialog(self): """ Create a dialog box to organize tags. """ # pylint: disable-msg=E1101 title = _("%(title)s - Gramps") % {'title': _("Organize Tags")} top = gtk.Dialog(title) top.set_default_size(400, 350) top.set_modal(True) top.set_transient_for(self.parent_window) top.set_has_separator(False) top.vbox.set_spacing(5) label = gtk.Label('<span size="larger" weight="bold">%s</span>' % _("Organize Tags")) label.set_use_markup(True) top.vbox.pack_start(label, 0, 0, 5) box = gtk.HBox() top.vbox.pack_start(box, 1, 1, 5) name_titles = [ ('', NOSORT, 20, INTEGER), # Priority ('', NOSORT, 100), # Handle (_('Name'), NOSORT, 200), (_('Color'), NOSORT, 50, COLOR) ] self.namelist = gtk.TreeView() self.namemodel = ListModel(self.namelist, name_titles) slist = gtk.ScrolledWindow() slist.add_with_viewport(self.namelist) slist.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) box.pack_start(slist, 1, 1, 5) bbox = gtk.VButtonBox() bbox.set_layout(gtk.BUTTONBOX_START) bbox.set_spacing(6) up = gtk.Button(stock=gtk.STOCK_GO_UP) down = gtk.Button(stock=gtk.STOCK_GO_DOWN) add = gtk.Button(stock=gtk.STOCK_ADD) edit = gtk.Button(stock=gtk.STOCK_EDIT) remove = gtk.Button(stock=gtk.STOCK_REMOVE) up.connect('clicked', self.cb_up_clicked) down.connect('clicked', self.cb_down_clicked) add.connect('clicked', self.cb_add_clicked, top) edit.connect('clicked', self.cb_edit_clicked, top) remove.connect('clicked', self.cb_remove_clicked, top) top.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) top.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP) bbox.add(up) bbox.add(down) bbox.add(add) bbox.add(edit) bbox.add(remove) box.pack_start(bbox, 0, 0, 5) top.show_all() return top
def build_gui(self): """ Build the GUI interface. """ top = gtk.TreeView() titles = [(_('Type'), 0, 100), (_('Name'), 1, 100), ('', 2, 1), #hidden column for the handle ('', 3, 1)] #hidden column for non-localized object type self.model = ListModel(top, titles, event_func=self.cb_double_click) return top
def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to view a quick report showing ' 'all people with the selected attribute.') self.set_tooltip(tip) top = gtk.TreeView() titles = [(_('Key'), 1, 100), (_('Value'), 2, 100)] self.model = ListModel(top, titles, event_func=self.display_report) return top
def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = gtk.TreeView() titles = [('', NOSORT, 50,), (_('Date'), 1, 200), (_('Place'), 2, 200)] self.model = ListModel(top, titles, event_func=self.edit_event) return top
class Attributes(Gramplet): """ Displays the attributes of an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to view a quick report showing ' 'all people with the selected attribute.') self.set_tooltip(tip) top = gtk.TreeView() titles = [(_('Key'), 1, 100), (_('Value'), 2, 100)] self.model = ListModel(top, titles, event_func=self.display_report) return top def display_attributes(self, obj): """ Display the attributes of an object. """ for attr in obj.get_attribute_list(): self.model.add((attr.get_type(), attr.get_value())) self.set_has_data(self.model.count > 0) def display_report(self, treeview): """ Display the quick report for matching attribute key. """ model, iter_ = treeview.get_selection().get_selected() if iter_: key = model.get_value(iter_, 0) run_quick_report_by_name(self.dbstate, self.uistate, 'attribute_match', key) def get_has_data(self, obj): """ Return True if the gramplet has data, else return False. """ if obj is None: return False if obj.get_attribute_list(): return True return False
def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected child.') self.set_tooltip(tip) top = gtk.TreeView() titles = [('', NOSORT, 50,), (_('Child'), 1, 250), (_('Birth Date'), 3, 100), ('', 3, 100), (_('Death Date'), 5, 100), ('', 5, 100)] self.model = ListModel(top, titles, event_func=self.edit_person) return top
def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = gtk.TreeView() titles = [( '', NOSORT, 50, ), (_('Type'), 1, 100), (_('Main Participants'), 2, 200), (_('Date'), 4, 100), ('', 4, 100), (_('Place'), 5, 400), (_('Description'), 6, 150), (_('Role'), 7, 100)] self.model = ListModel(top, titles, event_func=self.edit_event) return top
def _create_dialog(self): """ Create a dialog box to select tags. """ # pylint: disable-msg=E1101 title = _("%(title)s - Gramps") % {'title': _("Edit Tags")} top = gtk.Dialog(title) top.set_default_size(360, 400) top.set_modal(True) top.set_has_separator(False) top.vbox.set_spacing(5) columns = [('', -1, 300), (' ', -1, 25, TOGGLE, True, None), (_('Tag'), -1, 300)] view = gtk.TreeView() self.namemodel = ListModel(view, columns) slist = gtk.ScrolledWindow() slist.add_with_viewport(view) slist.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) top.vbox.pack_start(slist, 1, 1, 5) top.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP) top.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) top.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) top.show_all() return top
def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected source/citation.') self.set_tooltip(tip) top = gtk.TreeView() titles = [( '', NOSORT, 50, ), (_('Source/Citation'), 1, 350), (_('Author'), 2, 200), (_('Publisher'), 3, 150)] self.model = ListModel(top, titles, list_mode="tree", event_func=self.invoke_editor) return top
class ListView(QListView): def __init__(self, parent): super().__init__(parent=parent) self.m_pModel = ListModel([]) self.setModel(self.m_pModel) def contextMenuEvent(self, event): hitIndex = self.indexAt(event.pos()).column() if hitIndex > -1: pmenu = QMenu(self) pDownloadAct = QAction(QIcon('logo.jpg'), "抓取微博", pmenu) pmenu.addAction(pDownloadAct) pDownloadAct.triggered.connect(self.doScrapy) pOpenMenu = QAction(QIcon('logo.jpg'), "在浏览器中打开", pmenu) pmenu.addAction(pOpenMenu) pOpenMenu.triggered.connect(self.openInBrowser) pmenu.popup(self.mapToGlobal(event.pos())) def clearData(self): self.m_pModel = ListModel([]) self.setModel(self.m_pModel) def openInBrowser(self): index = self.currentIndex().row() url = "https://weibo.com/u/{}".format( self.m_pModel.getItem(index).get('uid')) print(url) webbrowser.open(url) def doScrapy(self): global vgs index = self.currentIndex().row() vgs.ps.emit(self.m_pModel.getItem(index).get('uid')) print(index) def addItem(self, pitem): self.m_pModel.addItem(pitem)
class PersonChildren(Children): """ Displays the children of a person. """ def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected child.') self.set_tooltip(tip) top = gtk.TreeView() titles = [('', NOSORT, 50,), (_('Child'), 1, 250), (_('Birth Date'), 3, 100), ('', 3, 100), (_('Death Date'), 5, 100), ('', 5, 100), (_('Spouse'), 6, 250)] self.model = ListModel(top, titles, event_func=self.edit_person) return top def db_changed(self): self.dbstate.db.connect('person-update', self.update) def active_changed(self, handle): self.update() def main(self): active_handle = self.get_active('Person') self.model.clear() if active_handle: self.display_person(active_handle) else: self.set_has_data(False) def update_has_data(self): active_handle = self.get_active('Person') active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) def get_has_data(self, active_person): """ Return True if the gramplet has data, else return False. """ if active_person is None: return False for family_handle in active_person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(family_handle) if family.get_child_ref_list(): return True return False def display_person(self, active_handle): """ Display the children of the active person. """ active_person = self.dbstate.db.get_person_from_handle(active_handle) for family_handle in active_person.get_family_handle_list(): family = self.dbstate.db.get_family_from_handle(family_handle) self.display_family(family, active_handle) self.set_has_data(self.model.count > 0) def display_family(self, family, active_handle): """ Display the children of given family. """ father_handle = family.get_father_handle() mother_handle = family.get_mother_handle() if father_handle == active_handle: spouse = self.dbstate.db.get_person_from_handle(mother_handle) else: spouse = self.dbstate.db.get_person_from_handle(father_handle) for child_ref in family.get_child_ref_list(): child = self.dbstate.db.get_person_from_handle(child_ref.ref) self.add_child(child, spouse) def add_child(self, child, spouse): """ Add a child to the model. """ name = name_displayer.display(child) if spouse: spouse = name_displayer.display(spouse) birth = get_birth_or_fallback(self.dbstate.db, child) birth_date, birth_sort, birth_place = self.get_date_place(birth) death = get_death_or_fallback(self.dbstate.db, child) death_date, death_sort, death_place = self.get_date_place(death) self.model.add((child.get_handle(), name, birth_date, birth_sort, death_date, death_sort, spouse))
class SpotipyModule(qtc.QObject): #Signals currTitleChanged = qtc.Signal() currArtistChanged = qtc.Signal() currIconChanged = qtc.Signal() durTimeChanged = qtc.Signal() def __init__(self, username, client_id, client_secret, redirect_url,user): super(SpotipyModule, self).__init__() # initalizes variables self.username = username self.client_id = client_id self.client_secret = client_secret self.redirect_url = redirect_url self.scope = 'user-library-read user-read-playback-state streaming' \ ' playlist-modify-public user-modify-playback-state playlist-modify-private ' \ 'user-read-playback-position user-read-currently-playing user-read-private' self.user = user self.spellchecker = spellchecker.SpellChecker(language=u'en', distance=2) self.queue_id = None self.playing = False self.queue_uri = None self.queue_changed = False self.current_queue = None self.playlist_ids = None self.playlist_names = None self.search_results = None self.dur_time = 0 self.artist = "" self.title = "" self.picture = qtc.QUrl() self.search_list = ListModel(SpotipyModule.SongWrapper) self.token = self.generate_token() self.queue = self.generate_queue() self.devices = self.token.devices() # generates access token for authorization to use spotify API def generate_token(self): token = util.prompt_for_user_token(self.username, self.scope, self.client_id, self.client_secret, self.redirect_url) #returns an authorized Spotify object if token is valid if token: sp = spy.Spotify(auth=token) return sp #generates a playlist that acts as a queue def generate_queue(self): playlists = self.token.user_playlists(self.user) #Checks Each Playlist to see if Queue exists for playlist in playlists['items']: #Sets Class Variables to Current Queue Variables if Queue exists if (playlist['name']) == 'Queue': self.queue_id = playlist['id'] self.queue_uri = playlist['uri'] self.current_queue = self.queue_uri #Makes Queue Playlist if not found if(self.queue_id is None): self.token.user_playlist_create(self.user,'Queue', public=True, description="Queue made by Yours Truly, Jarvis") playlists = self.token.user_playlists(self.user) self.queue_id = playlists['items'][0]['id'] self.queue_uri = playlists['items'][0]['uri'] self.current_queue = self.queue_uri return ''' Adds a song to the queue playlist and Obtains title, picture, and artist for QML Display Args: str(spotify id of a song) ''' @qtc.Slot(str) def add_song_to_queue(self, song_title): # search_query = song_title.replace(" ", "&20") # print(search_query) # Find all songs that show up for this query self.search_results = (self.token.search(song_title, 10, 0, type='track,album')) self.search_list.clear() # loop places song titles into list of possible songs for temp in self.search_results['tracks']['items']: title = temp['name'] picture_image = temp['album']['images'][1]['url'] artist = temp['artists'][0]['name'] self.search_list.appendRow(SpotipyModule.SongWrapper(title, artist, picture_image, self.search_list)) return ''' Allows User to Choose a Song Based on Search Results from query. Args: Number of Chosen song ''' @qtc.Slot(int) def helper_add_song_to_queue(self, number): # Change the queue to the default queue if self.current_queue != self.queue_uri: self.current_queue = self.queue_uri self.queue_changed = True self.search_list.clear() #Obtains specific song Information from Queried Song List based on Number temp = self.search_results['tracks']['items'][number] song = temp['uri'] #Adds specifcied song into Playlist self.token.user_playlist_add_tracks(self.user, self.queue_id, tracks=[song]) return # Plays Music from Queue Playlist or a Specified Playlist @qtc.Slot() def play_music(self): #Starts Playing Songs in Queue and Sets the current playing song info in Front end if(self.playing == False): print("Entered") self.token.start_playback(context_uri=self.current_queue) self.token.shuffle(False) time.sleep(.1) self.set_current_song_info() else: # Starts the playback of specified Playlist if self.queue_changed: self.token.start_playback(context_uri=self.current_queue) self.queue_changed = False else: self.token.start_playback() self.token.shuffle(False) self.playing = True return # Pauses music @qtc.Slot() def pause_music(self): self.token.pause_playback() return #Sets the Current time of the song, Artist, Picture, and Title of the song that is playing @qtc.Slot() def set_current_song_info(self): try: #Obtain Current Song Data temp = self.token.current_user_playing_track()['item'] song_title = temp['name'] #Checks if information is already set if(song_title == self.title): return self.set_durTime(temp['duration_ms']) self.set_currArtist(temp['artists'][0]['name']) self.set_currIcon(temp['album']['images'][0]['url']) self.set_currTitle(song_title) return # If Spotipy is not playing anything... ie self.token.set_current_song_info = None; return except TypeError: return #Gets the Progression of the Time of the Current Song @qtc.Slot(result=int) def get_current_time(self): #If song is not playing, Time is 0 if(not self.playing): return 0 songtime = self.token.current_user_playing_track()['progress_ms'] time.sleep(.03) return songtime #Returns Title of Current Song @qtc.Property(str, notify=currTitleChanged) def currTitle(self): return self.title #Sends Signal when Current Title is Changed @currTitle.setter def set_currTitle(self, new_title): if self.title == new_title: return self.title = new_title self.currTitleChanged.emit() #Returns Album/Playlist Cover of Song @qtc.Property(qtc.QUrl, notify=currIconChanged) def currIcon(self): return self.picture #Sends Signal when Current Picture is Changed @currIcon.setter def set_currIcon(self, new_icon): if self.picture == new_icon: return self.picture = new_icon self.currIconChanged.emit() #Returns Artist of Current Song @qtc.Property(qtc.QUrl, notify=currArtistChanged) def currArtist(self): return self.artist #Sends Signal when Current Artist is Changed @currArtist.setter def set_currArtist(self, new_artist): if self.artist == new_artist: return self.artist = new_artist self.currArtistChanged.emit() #Returns Time of Progress of Song in seconds @qtc.Property(float, notify=durTimeChanged) def durTime(self): if self.dur_time == 0: return 10000 return self.dur_time #Sends Signal when Progression of Song is changed @durTime.setter def set_durTime(self,time): if self.dur_time == time: return else: self.dur_time = time self.durTimeChanged.emit() # changes volume of current song @qtc.Slot(int) def change_volume(self, value): if self.token.current_user_playing_track() is not None: self.token.volume(value) return value # allows user to start playing in middle of song @qtc.Slot(int, result=int) def change_time(self, song_time): #If User sets a songtime within the time limit, time sets: else, dur_time remains the same if song_time >= 0 and song_time < self.dur_time: self.token.seek_track(position_ms=song_time) return song_time elif song_time >= self.dur_time: self.token.seek_track(position_ms=self.dur_time) else: return @qtc.Slot() # skips current song to next in queue/playlist def next_song(self): self.token.next_track() time.sleep(.1) self.set_current_song_info() return @qtc.Slot() # goes back 1 song def prev_song(self): self.token.previous_track() time.sleep(.1) self.set_current_song_info() return ''' Finds a List of Playlist based on a Query Args: Playlist_title: A query for a playlist name Returns: A list of playlists that matches closely to query ''' @qtc.Slot(str) def find_a_playlist(self, playlist_title): #Obtains list of 20 playlist id's search_results = self.token.search(playlist_title, 20, 0, 'playlist') if len(search_results['playlists']['items']) == 0: self.spellchecker.split_words(playlist_title) #initalizes list to hold data from each playlist playlist_number = 1 playlist_index = 0 playlist_to_be_queued = [None] * len(search_results['playlists']['items']) playlist_ids = [None] * len(search_results['playlists']['items']) # Clear the search list self.search_list.clear() # Add the playlists to the search list for songz in range(0, len(search_results['playlists']['items'])): name = str(playlist_number) + ') ' + search_results['playlists']['items'][songz]['name'] author = search_results['playlists']['items'][songz]['owner']['display_name'] playlist_ids[playlist_index] = search_results['playlists']['items'][songz]['uri'] self.search_list.appendRow(SpotipyModule.SongWrapper(name, author, "", self.search_list)) playlist_number += 1 playlist_index += 1 self.playlist_ids = playlist_ids self.playlist_names = playlist_to_be_queued return self.playlist_ids # plays songs from a specific playlist @qtc.Slot(int) def queue_music_from_playlist(self, index): # Clear the search list self.search_list.clear() playlist = self.playlist_ids[index] self.current_queue = playlist self.queue_changed = True self.play_music() return def destroyer(self): self.token.user_playlist_unfollow(user=self.user, playlist_id=self.queue_id) return #SongWrapper is a wrapper that wraps an object in a Qt object class SongWrapper(qtc.QObject): # Dictionary of roles for SongWrapper roles = { qtc.Qt.UserRole + 1: b'song', qtc.Qt.UserRole + 2: b'artist', qtc.Qt.UserRole + 3: b'image_url' } # Signals #songChanged = qtc.Signal() #artistChanged = qtc.Signal() #image_urlChanged = qtc.Signal() # Initialize the wrapper def __init__(self, song, artist, image_url, parent=None): super(SpotipyModule.SongWrapper, self).__init__() self._data = {b'song': song, b'artist': artist, b'image_url': image_url} # Retrieves the given role of the SongWrapper (i.e. song, artist, or image_url) def data(self, key): return self._data[self.roles[key]] @qtc.Property(str) def song(self): return self._data[b'song'] @qtc.Property(str) def artist(self): return self._data[b'artist'] @qtc.Property(qtc.QUrl) def image_url(self): return self._data[b'image_url'] def __str__(self): return "[" + str(self.song) + ", " + str(self.artist) + "]" def __repr__(self): return str(self)
def __init__(self): gtk.TreeView.__init__(self) self.sections = {} titles = [(_('Key'), 1, 235), (_('Value'), 2, 325)] self.model = ListModel(self, titles, list_mode="tree")
class MetadataView(gtk.TreeView): def __init__(self): gtk.TreeView.__init__(self) self.sections = {} titles = [(_('Key'), 1, 235), (_('Value'), 2, 325)] self.model = ListModel(self, titles, list_mode="tree") def display_exif_tags(self, full_path): """ Display the exif tags. """ # pylint: disable=E1101 self.sections = {} self.model.clear() if OLD_API: # prior to v0.2.0 try: metadata = pyexiv2.Image(full_path) except IOError: return False metadata.readMetadata() for section, key, key2, func in TAGS: if key not in metadata.exifKeys(): continue if func is not None: if key2 is None: human_value = func(metadata[key]) else: if key2 in metadata.exifKeys(): human_value = func(metadata[key], metadata[key2]) else: human_value = func(metadata[key], None) else: human_value = metadata.interpretedExifValue(key) if key2 is not None and key2 in metadata.exifKeys(): human_value += ' ' + metadata.interpretedExifValue(key2) label = metadata.tagDetails(key)[0] node = self.__add_section(section) self.model.add((label, human_value), node=node) else: # v0.2.0 and above metadata = pyexiv2.ImageMetadata(full_path) try: metadata.read() except IOError: return False for section, key, key2, func in TAGS: if key not in metadata.exif_keys: continue tag = metadata.get(key) if key2 is not None and key2 in metadata.exif_keys: tag2 = metadata.get(key2) else: tag2 = None if func is not None: if key2 is None: human_value = func(tag.value) else: if tag2 is None: human_value = func(tag.value, None) else: human_value = func(tag.value, tag2.value) else: human_value = tag.human_value if tag2 is not None: human_value += ' ' + tag2.human_value label = tag.label node = self.__add_section(section) self.model.add((tag.label, human_value), node=node) self.model.tree.expand_all() return self.model.count > 0 def __add_section(self, section): """ Add the section heading node to the model. """ if section not in self.sections: node = self.model.add([section, '']) self.sections[section] = node else: node = self.sections[section] return node def get_has_data(self, full_path): """ Return True if the gramplet has data, else return False. """ # pylint: disable=E1101 if OLD_API: # prior to v0.2.0 try: metadata = pyexiv2.Image(full_path) except IOError: return False metadata.readMetadata() for tag in TAGS: if tag[1] in metadata.exifKeys(): return True else: # v0.2.0 and above metadata = pyexiv2.ImageMetadata(full_path) try: metadata.read() except IOError: return False for tag in TAGS: if tag[1] in metadata.exif_keys: return True return False
class PersonResidence(Gramplet): """ Displays residence events for a person. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = gtk.TreeView() titles = [('', NOSORT, 50,), (_('Date'), 1, 200), (_('Place'), 2, 200)] self.model = ListModel(top, titles, event_func=self.edit_event) return top def db_changed(self): self.dbstate.db.connect('person-update', self.update) def active_changed(self, handle): self.update() def update_has_data(self): active_handle = self.get_active('Person') active = self.dbstate.db.get_person_from_handle(active_handle) self.set_has_data(self.get_has_data(active)) def get_has_data(self, active_person): """ Return True if the gramplet has data, else return False. """ if active_person: for event_ref in active_person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if int(event.get_type()) == EventType.RESIDENCE: return True return False def main(self): # return false finishes active_handle = self.get_active('Person') active_person = self.dbstate.db.get_person_from_handle(active_handle) self.model.clear() if active_person: self.display_person(active_person) else: self.set_has_data(False) def display_person(self, active_person): """ Display the residence events of the active person. """ count = 0 for event_ref in active_person.get_event_ref_list(): if int(event_ref.get_role()) == EventRoleType.PRIMARY: event = self.dbstate.db.get_event_from_handle(event_ref.ref) if int(event.get_type()) == EventType.RESIDENCE: self.add_residence(event) count += 1 self.set_has_data(count > 0) def add_residence(self, event): """ Add a residence event to the model. """ date = DateHandler.get_date(event) place = '' handle = event.get_place_handle() if handle: place = self.dbstate.db.get_place_from_handle(handle).get_title() self.model.add((event.get_handle(), date, place)) def edit_event(self, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except Errors.WindowActiveError: pass
def __init__(self): super().__init__() self.m_pModel = ListModel() self.setModel(self.m_pModel)
def __init__(self, uistate, track, addon_update_list): self.title = _('Available Gramps Updates for Addons') ManagedWindow.ManagedWindow.__init__(self, uistate, track, self.__class__) glade = Glade("updateaddons.glade") self.update_dialog = glade.toplevel self.set_window(self.update_dialog, glade.get_object('title'), self.title) self.window.set_size_request(750, 400) apply_button = glade.get_object('apply') cancel_button = glade.get_object('cancel') select_all = glade.get_object('select_all') select_all.connect("clicked", self.select_all_clicked) select_none = glade.get_object('select_none') select_none.connect("clicked", self.select_none_clicked) apply_button.connect("clicked", self.install_addons) cancel_button.connect("clicked", self.close) self.list = ListModel( glade.get_object("list"), [ # name, click?, width, toggle { "name": _('Select'), "width": 60, "type": TOGGLE, "visible_col": 6, "editable": True }, # 0 selected? (_('Type'), 1, 180), # 1 new gramplet (_('Name'), 2, 200), # 2 name (version) (_('Description'), 3, 200), # 3 description ('', NOSORT, 0), # 4 url ('', NOSORT, 0), # 5 id { "name": '', "type": TOGGLE }, # 6 visible? bool ], list_mode="tree") pos = None addon_update_list.sort(key=lambda x: "%s %s" % (x[0], x[2]["t"])) last_category = None for (status, plugin_url, plugin_dict) in addon_update_list: count = get_count(addon_update_list, plugin_dict["t"]) category = _("%(adjective)s: %(addon)s") % { "adjective": status, "addon": _(plugin_dict["t"]) } if last_category != category: last_category = category node = self.list.add([ False, # initially selected? category, "", "", "", "", False ]) # checkbox visible? iter = self.list.add( [ False, # initially selected? "%s %s" % (status, _(plugin_dict["t"])), "%s (%s)" % (plugin_dict["n"], plugin_dict["v"]), plugin_dict["d"], plugin_url, plugin_dict["i"], True ], node=node) if pos is None: pos = iter if pos: self.list.selection.select_iter(pos) self.update_dialog.run()
def __init__(self, parent): super().__init__(parent=parent) self.m_pModel = ListModel([]) self.setModel(self.m_pModel)
class Events(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the events for a person or family. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'event-update': self.changed}) self.callman.connect_all(keys=['event']) def changed(self, handle): """ Called when a registered event is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected event.') self.set_tooltip(tip) top = gtk.TreeView() titles = [( '', NOSORT, 50, ), (_('Type'), 1, 100), (_('Main Participants'), 2, 200), (_('Date'), 4, 100), ('', 4, 100), (_('Place'), 5, 400), (_('Description'), 6, 150), (_('Role'), 7, 100)] self.model = ListModel(top, titles, event_func=self.edit_event) return top def add_event_ref(self, event_ref, spouse=None): """ Add an event to the model. """ self.callman.register_handles({'event': [event_ref.ref]}) event = self.dbstate.db.get_event_from_handle(event_ref.ref) event_date = DateHandler.get_date(event) event_sort = '%012d' % event.get_date_object().get_sort_value() place = '' handle = event.get_place_handle() if handle: place = self.dbstate.db.get_place_from_handle(handle).get_title() participants = '' if int(event_ref.get_role()) == EventRoleType.FAMILY: if spouse: participants = name_displayer.display(spouse) participants = Utils.get_participant_from_event( self.dbstate.db, event_ref.ref) self.model.add((event.get_handle(), str(event.get_type()), participants, event_date, event_sort, place, event.get_description(), str(event_ref.get_role()))) def edit_event(self, treeview): """ Edit the selected event. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) try: event = self.dbstate.db.get_event_from_handle(handle) EditEvent(self.dbstate, self.uistate, [], event) except Errors.WindowActiveError: pass
class Citations(Gramplet, DbGUIElement): def __init__(self, gui, nav_group=0): Gramplet.__init__(self, gui, nav_group) DbGUIElement.__init__(self, self.dbstate.db) """ Displays the citations for an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add(self.gui.WIDGET) self.gui.WIDGET.show() def _connect_db_signals(self): """ called on init of DbGUIElement, connect to db as required. """ self.callman.register_callbacks({'citation-update': self.changed}) self.callman.connect_all(keys=['citation']) def changed(self, handle): """ Called when a registered citation is updated. """ self.update() def build_gui(self): """ Build the GUI interface. """ tip = _('Double-click on a row to edit the selected source/citation.') self.set_tooltip(tip) top = gtk.TreeView() titles = [( '', NOSORT, 50, ), (_('Source/Citation'), 1, 350), (_('Author'), 2, 200), (_('Publisher'), 3, 150)] self.model = ListModel(top, titles, list_mode="tree", event_func=self.invoke_editor) return top def add_citations(self, obj): for citation_handle in obj.get_citation_list(): self.add_citation_ref(citation_handle) def add_name_citations(self, obj): names = [obj.get_primary_name()] + obj.get_alternate_names() for name in names: self.add_citations(name) def add_attribute_citations(self, obj): for attr in obj.get_attribute_list(): self.add_citations(attr) def add_mediaref_citations(self, obj): for media_ref in obj.get_media_list(): self.add_citations(media_ref) self.add_attribute_citations(media_ref) media = self.dbstate.db.get_object_from_handle(media_ref.ref) self.add_media_citations(media) def add_media_citations(self, media): self.add_citations(media) self.add_attribute_citations(media) def add_eventref_citations(self, obj): for event_ref in obj.get_event_ref_list(): self.add_attribute_citations(event_ref) event = self.dbstate.db.get_event_from_handle(event_ref.ref) self.add_event_citations(event) def add_event_citations(self, event): self.add_citations(event) self.add_attribute_citations(event) self.add_mediaref_citations(event) place_handle = event.get_place_handle() place = self.dbstate.db.get_place_from_handle(place_handle) if place: self.add_place_citations(place) def add_place_citations(self, place): self.add_citations(place) self.add_mediaref_citations(place) def add_address_citations(self, obj): for address in obj.get_address_list(): self.add_citations(address) def add_lds_citations(self, obj): for lds in obj.get_lds_ord_list(): self.add_citations(lds) place_handle = lds.get_place_handle() place = self.dbstate.db.get_place_from_handle(place_handle) if place: self.add_place_citations(place) def add_association_citations(self, obj): for assoc in obj.get_person_ref_list(): self.add_citations(assoc) def add_citation_ref(self, citation_handle): """ Add a citation to the model. """ self.callman.register_handles({'citation': [citation_handle]}) citation = self.dbstate.db.get_citation_from_handle(citation_handle) page = citation.get_page() if not page: page = _('<No Citation>') source_handle = citation.get_reference_handle() source = self.dbstate.db.get_source_from_handle(source_handle) title = source.get_title() author = source.get_author() publisher = source.get_publication_info() if source_handle not in self.source_nodes: node = self.model.add([source_handle, title, author, publisher]) self.source_nodes[source_handle] = node self.model.add([citation_handle, page, '', ''], node=self.source_nodes[source_handle]) def check_citations(self, obj): return True if obj.get_citation_list() else False def check_name_citations(self, obj): names = [obj.get_primary_name()] + obj.get_alternate_names() for name in names: if self.check_citations(name): return True return False def check_attribute_citations(self, obj): for attr in obj.get_attribute_list(): if self.check_citations(attr): return True return False def check_mediaref_citations(self, obj): for media_ref in obj.get_media_list(): if self.check_citations(media_ref): return True if self.check_attribute_citations(media_ref): return True media = self.dbstate.db.get_object_from_handle(media_ref.ref) if self.check_media_citations(media): return True return False def check_media_citations(self, media): if self.check_citations(media): return True if self.check_attribute_citations(media): return True return False def check_eventref_citations(self, obj): for event_ref in obj.get_event_ref_list(): if self.check_attribute_citations(event_ref): return True event = self.dbstate.db.get_event_from_handle(event_ref.ref) if self.check_event_citations(event): return True return False def check_event_citations(self, event): if self.check_citations(event): return True if self.check_attribute_citations(event): return True if self.check_mediaref_citations(event): return True place_handle = event.get_place_handle() place = self.dbstate.db.get_place_from_handle(place_handle) if place and self.check_place_citations(place): return True return False def check_place_citations(self, place): if self.check_citations(place): return True if self.check_mediaref_citations(place): return True return False def check_address_citations(self, obj): for address in obj.get_address_list(): if self.check_citations(address): return True return False def check_lds_citations(self, obj): for lds in obj.get_lds_ord_list(): if self.check_citations(lds): return True place_handle = lds.get_place_handle() place = self.dbstate.db.get_place_from_handle(place_handle) if place and self.check_place_citations(place): return True return False def check_association_citations(self, obj): for assoc in obj.get_person_ref_list(): if self.check_citations(assoc): return True return False def invoke_editor(self, treeview): """ Edit the selected source or citation. """ model, iter_ = treeview.get_selection().get_selected() if iter_: handle = model.get_value(iter_, 0) if len(model.get_path(iter_)) == 1: self.edit_source(handle) else: self.edit_citation(handle) def edit_source(self, handle): """ Edit the selected source. """ try: source = self.dbstate.db.get_source_from_handle(handle) EditSource(self.dbstate, self.uistate, [], source) except Errors.WindowActiveError: pass def edit_citation(self, handle): """ Edit the selected citation. """ try: citation = self.dbstate.db.get_citation_from_handle(handle) source_handle = citation.get_reference_handle() source = self.dbstate.db.get_source_from_handle(source_handle) EditCitation(self.dbstate, self.uistate, [], citation, source) except Errors.WindowActiveError: pass
class GmailModule(qtc.QObject): loaded = qtc.Signal() def __init__(self): super(GmailModule, self).__init__() self.scopes = ['https://mail.google.com/'] self.time_elapsed = 0 self.currentEmailList = ListModel(GmailModule.EmailObject) self.threadMessages = ListModel(GmailModule.EmailObject) #print("Gmail finished") # Initializes the gmail widget in the qml file @qtc.Slot(int) def init_gmail_in_widget(self, parm): self.service = self.use_token_pickle_to_get_service() self.messages = self.service.users().messages() self.message_ids = self.get_list_of_users_message_ids() self.label_list = self.get_labels() threading.Thread(target=self.get_preview_message_info, args=(parm, )).start() ''' Accesses a file to gain saved credentials if no file exists the file is generated and user is asked to put in creds ''' def use_token_pickle_to_get_service(self): creds = None # The file token.pickle stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. if os.path.exists('token_gmail.pickle'): with open('token_gmail.pickle', 'rb') as token: creds = pickle.load(token) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( 'credentials_gmail.json', self.scopes) creds = flow.run_local_server(port=0) # Save the credentials for the next run with open('token_gmail.pickle', 'wb') as token: pickle.dump(creds, token) service = build('gmail', 'v1', credentials=creds) return service @qtc.Slot() def get_labels(self): results = self.service.users().labels().list(userId='me').execute() labels = results.get('labels', []) if not labels: return else: label_list = [None] * len(labels) label_list_index = 0 for label in labels: label_list[label_list_index] = (label['name']) label_list_index += 1 return label_list def get_list_of_users_message_ids(self): emails = self.messages.list(userId='me').execute() list_of_msg_ids = [None] * len(emails['messages']) index = 0 for email in range(0, len(emails['messages'])): list_of_msg_ids[index] = (emails['messages'][email]) index += 1 return list_of_msg_ids @qtc.Slot(int, result=str) def get_message_id(self, i): return self.message_ids[i]['id'] @qtc.Slot(int, result=str) def get_label(self, i): return self.label_list[i] # Takes an integer as an index and retrieves the message's metadata @qtc.Slot(int) def get_preview_message_info(self, num_messages): for index in range(0, num_messages): message = self.messages.get(userId='me', id=self.message_ids[index]['id'], format='metadata', metadataHeaders=[ "To", "From", "Subject", "References", "Message-ID" ]).execute() self.currentEmailList.appendRow( GmailModule.EmailObject(sender=self.GetSender(message), snippet=self.GetSnippet(message), subject=self.GetSubjectTitle(message), threadid=self.GetThread(message), references=self.GetReferences(message), messageid=self.GetMessageID(message))) return @qtc.Slot(str, result=str) def GetMessage(self, message): try: try: raw_msg = message['payload']['parts'][0]['body']['data'] msg_str = base64.urlsafe_b64decode(raw_msg.encode('ASCII')) #print(msg_str) # print ('Message snippet: %s' % message['payload']['body']['data']) except KeyError: if 'parts' in message['payload'] and 'parts' in message[ 'payload']['parts'][0]: if 'data' in (message['payload']['parts'][0]['parts'][0] ['body']): raw_msg = (message['payload']['parts'][0]['parts'][0] ['body']['data']) msg_str = base64.urlsafe_b64decode( raw_msg.encode('ASCII')) else: raw_msg = (message['payload']['parts'][0]['parts'][0] ['parts'][0]['body']['data']) msg_str = base64.urlsafe_b64decode( raw_msg.encode('ASCII')) elif 'parts' in message['payload'] and 'data' not in message[ 'payload']['parts'][0]['body']: raw_msg = ((message['payload']['parts'][0]['parts'][1] ['body']['data'])) msg_str = base64.urlsafe_b64decode(raw_msg.encode('ASCII')) elif 'parts' in message['payload'] and 'data' in ( message['payload']['parts'][0]['body']): raw_msg = (( message['payload']['parts'][0]['body']['data'])) msg_str = base64.urlsafe_b64decode(raw_msg.encode('ASCII')) else: raw_msg = message['payload']['body']['data'] msg_str = base64.urlsafe_b64decode(raw_msg.encode('ASCII')) return msg_str return msg_str except apiclient.errors.HttpError: return @qtc.Slot(str, result=str) def GetSender(self, message): try: for i in range(0, len((message['payload']['headers']))): if (message['payload']['headers'][i]['name']) == 'From': sender = ((message['payload']['headers'][i]['value'])) return sender return except apiclient.errors.HttpError: return @qtc.Slot(str, result=str) def GetSubjectTitle(self, message): try: for i in range(0, len((message['payload']['headers']))): if (message['payload']['headers'][i]['name']) == 'Subject': subject = ((message['payload']['headers'][i]['value'])) return subject except apiclient.errors.HttpError: return @qtc.Slot(str, result=str) def GetSnippet(self, message): try: snippet = message['snippet'] return snippet except apiclient.errors.HttpError: return @qtc.Slot(str, result=str) def GetThread(self, message): try: return message['threadId'] except apiclient.errors.HttpError: return @qtc.Slot(str, result=str) def GetReferences(self, message): try: for i in range(0, len((message['payload']['headers']))): if (message['payload']['headers'][i]['name']) == 'References': references = ((message['payload']['headers'][i]['value'])) return references except apiclient.errors.HttpError: return @qtc.Slot(str, result=str) def GetMessageID(self, message): try: for i in range(0, len((message['payload']['headers']))): if (message['payload']['headers'][i]['name']) == 'Message-ID': messageID = ((message['payload']['headers'][i]['value'])) return messageID except apiclient.errors.HttpError: return @qtc.Slot() def ListMessagesMatchingQuery(self, user_id, query=''): try: response = self.messages.list(userId='me', q=query).execute() messages = [] if 'messages' in response: messages.extend(response['messages']) while 'nextPageToken' in response: page_token = response['nextPageToken'] response = self.messages.list(userId=user_id, q=query, pageToken=page_token).execute() messages.extend(response['messages']) return messages except apiclient.errors.HttpError as error: return @qtc.Slot(str) def get_messages_with_labels(self, label_ids=''): try: response = self.messages.list(userId='me', labelIds=label_ids).execute() messages = [] if 'messages' in response: messages.extend(response['messages']) while 'nextPageToken' in response and len(messages) <= 50: page_token = response['nextPageToken'] response = self.messages.list(userId='me', labelIds=label_ids, pageToken=page_token).execute() messages.extend(response['messages']) # Add the response to the list of emails self.currentEmailList.clear() i = 0 while i < 20 and i < len(messages): message = self.messages.get(userId='me', id=messages[i]['id'], format='metadata', metadataHeaders=[ "To", "From", "Subject", "References", "Message-ID" ]).execute() self.currentEmailList.appendRow( GmailModule.EmailObject( sender=self.GetSender(message), snippet=self.GetSnippet(message), subject=self.GetSubjectTitle(message), threadid=self.GetThread(message), references=self.GetReferences(message), messageid=self.GetMessageID(message))) i += 1 return messages except apiclient.errors.HttpError as error: return @qtc.Slot(str) def get_messages_from_query(self, query=''): try: response = self.messages.list(userId='me', maxResults=50, q=query).execute() messages = [] if 'messages' in response: messages.extend(response['messages']) while 'nextPageToken' in response: page_token = response['nextPageToken'] response = self.messages.list(userId='me', q=query, pageToken=page_token).execute() messages.extend(response['messages']) self.currentEmailList.clear() #print(messages)] i = 0 while i < 10 and i < len(messages): message = self.messages.get(userId='me', id=messages[i]['id'], format='metadata', metadataHeaders=[ "To", "From", "Subject", "References", "Message-ID" ]).execute() self.currentEmailList.appendRow( GmailModule.EmailObject( sender=self.GetSender(message), snippet=self.GetSnippet(message), subject=self.GetSubjectTitle(message), threadid=self.GetThread(message), references=self.GetReferences(message), messageid=self.GetMessageID(message))) i += 1 return except apiclient.errors.HttpError as error: return def list_message_ids(self): emails = self.messages.list(userId='me').execute() return emails def create_email(self, sender, to, subject, message_text, file_dir, filename): message = MIMEMultipart() message['to'] = to message['from'] = sender message['subject'] = subject msg = MIMEText(message_text) message.attach(msg) path = os.path.join(file_dir, filename) content_type, encoding = mimetypes.guess_type(path) if content_type is None or encoding is not None: content_type = 'application/octet-stream' main_type, sub_type = content_type.split('/', 1) if main_type == 'text': fp = open(path, 'rb') msg = MIMEText(fp.read(), _subtype=sub_type) fp.close() elif main_type == 'image': fp = open(path, 'rb') msg = MIMEImage(fp.read(), _subtype=sub_type) fp.close() elif main_type == 'audio': fp = open(path, 'rb') msg = MIMEAudio(fp.read(), _subtype=sub_type) fp.close() else: fp = open(path, 'rb') msg = MIMEBase(main_type, sub_type) msg.set_payload(fp.read()) fp.close() msg.add_header('Content-Disposition', 'attachment', filename=filename) message.attach(msg) return {'raw': base64.urlsafe_b64encode(message.as_string())} @qtc.Slot(str, str, str, str, str, result=dict) def create_basic_email(self, sender, to, subject, message_text, ref=None, in_reply=None): message = MIMEText(message_text) message['to'] = to message['from'] = sender message['subject'] = subject # Add referecena and in reply to headers if they are set if (not (ref is None) and not (in_reply is None)): message['References'] = ref message['In-Reply-To'] = in_reply #print(ref) #print(in_reply) return {'raw': base64.urlsafe_b64encode((message.as_bytes())).decode()} @qtc.Slot(str, str, str, str) def send_message(self, sender, to, subject, message_text): # Return early if there is no sender if (sender == "" or sender.isspace() or sender is None): return premessage = self.create_basic_email(sender, to, subject, message_text) try: message = (self.messages.send(userId=sender, body=premessage).execute()) return message except apiclient.errors.HttpError as error: print('error') return def get_thread(self, query=''): response = self.service.users().threads().list(userId='me', q=query).execute() return def get_messages_from_a_thread(self, thread_id): try: response = self.service.users().threads().get( userId='me', id=thread_id).execute() except: return all_messages = response['messages'] result = [] for message in range(0, len(all_messages)): try: raw_msg = (all_messages[message]['payload']['parts'][0]['body'] ['data']) except KeyError: raw_msg = all_messages[message]['payload']['body']['data'] msg_str = self.GetSender( all_messages[message]) + "\n" + base64.urlsafe_b64decode( raw_msg.encode('ASCII')).decode('utf-8') result.append(msg_str) return result msg_str = (base64.urlsafe_b64decode( raw_msg.encode())).decode('utf-8') result.append(msg_str) return result @qtc.Slot(int) def add_thread_messages(self, index): self.threadMessages.clear() threadid = self.currentEmailList.get(index, qtc.Qt.UserRole + 9) thread_messages = self.get_messages_from_a_thread(threadid) if (thread_messages is None): return for msg in thread_messages: self.threadMessages.appendRow( GmailModule.EmailObject(sender="", snippet="", subject="", threadid=threadid, message=msg)) @qtc.Slot(str, str, str, str, str, str, str, result=str) def respond_to_thread(self, thread_id, sender, to, subject, msg_id, references, message_text): # Return early if there is no sender if (sender == "" or sender.isspace() or sender is None): return ref = references if (references != ""): ref = references + " " + msg_id else: ref = msg_id premessage = self.create_basic_email(sender, to, subject, message_text, ref=ref, in_reply=msg_id) premessage['threadId'] = thread_id print("References ", ref) print("Message ID ", msg_id) print("Subject ", subject) try: message = (self.messages.send(userId=sender, body=premessage).execute()) return message except apiclient.errors.HttpError as error: print('error') return return @qtc.Slot(int, result=str) def get_current_threadid(self, index): return self.currentEmailList.get(index, qtc.Qt.UserRole + 9) @qtc.Slot(int, result=str) def get_current_sender(self, index): return self.currentEmailList.get(index, qtc.Qt.UserRole + 4) @qtc.Slot(int, result=str) def get_current_subject(self, index): return self.currentEmailList.get(index, qtc.Qt.UserRole + 6) @qtc.Slot(int, result=str) def get_current_message_id(self, index): return self.currentEmailList.get(index, qtc.Qt.UserRole + 10) @qtc.Slot(int, result=str) def get_current_references(self, index): return self.currentEmailList.get(index, qtc.Qt.UserRole + 11) class EmailObject(qtc.QObject): # Roles roles = { qtc.Qt.UserRole + 4: b'sender', qtc.Qt.UserRole + 5: b'receiver', qtc.Qt.UserRole + 6: b'subject', qtc.Qt.UserRole + 7: b'snippet', qtc.Qt.UserRole + 8: b'message', qtc.Qt.UserRole + 9: b'threadid', qtc.Qt.UserRole + 10: b'messageid', qtc.Qt.UserRole + 11: b'references' } # Signals senderChanged = qtc.Signal() receiverChanged = qtc.Signal() subjectChanged = qtc.Signal() snippetChanged = qtc.Signal() messageChanged = qtc.Signal() threadidChanged = qtc.Signal() # Initializer for email object def __init__(self, sender=None, receiver=None, subject=None, snippet=None, message=None, threadid=None, messageid=None, references=None): super(GmailModule.EmailObject, self).__init__() self._data = { b'sender': sender, b'receiver': receiver, b'subject': subject, b'snippet': snippet, b'message': message, b'threadid': threadid, b'messageid': messageid, b'references': references } # Retrieves the data def data(self, key): return self._data[self.roles[key]] @qtc.Property(str) def sender(self): self._data[b'sender'] @qtc.Property(str) def receiver(self): return self._data[b'receiver'] @qtc.Property(str) def subject(self): return self._data[b'subject'] @qtc.Property(str) def snippet(self): return self._data[b'snippet'] @qtc.Property(str) def message(self): return self._data[b'message'] @qtc.Property(str) def threadid(self): return self._data[b'threadid'] @qtc.Property(str) def messageid(self): return self._data[b'messageid'] @qtc.Property(str) def references(self): return self._data[b'references'] def __str__(self): return "[" + self.sender + " " + self.receiver + " " + self.subject + ']' def __repr__(self): return str(self)
class OrganizeTagsDialog(object): """ A dialog to enable the user to organize tags. """ def __init__(self, db, parent_window): self.db = db self.parent_window = parent_window self.namelist = None self.namemodel = None self.top = self._create_dialog() def run(self): """ Run the dialog and return the result. """ self._populate_model() while True: response = self.top.run() if response == gtk.RESPONSE_HELP: GrampsDisplay.help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC) else: break # Save changed priority values if self.__priorities_changed(): with DbTxn(_('Change Tag Priority'), self.db) as trans: self.__change_tag_priority(trans) self.top.destroy() def __priorities_changed(self): """ Return True if the tag priorities have changed else return False. """ priorities = [row[0] for row in self.namemodel.model] return priorities != range(len(self.namemodel.model)) def __change_tag_priority(self, trans): """ Change the priority of the tags. The order of the list corresponds to the priority of the tags. The top tag in the list is the highest priority tag. """ for new_priority, row in enumerate(self.namemodel.model): if row[0] != new_priority: tag = self.db.get_tag_from_handle(row[1]) if tag: tag.set_priority(new_priority) self.db.commit_tag(tag, trans) def _populate_model(self): """ Populate the model. """ self.namemodel.clear() tags = [] for tag in self.db.iter_tags(): tags.append((tag.get_priority(), tag.get_handle(), tag.get_name(), tag.get_color())) for row in sorted(tags): self.namemodel.add(row) def _create_dialog(self): """ Create a dialog box to organize tags. """ # pylint: disable-msg=E1101 title = _("%(title)s - Gramps") % {'title': _("Organize Tags")} top = gtk.Dialog(title) top.set_default_size(400, 350) top.set_modal(True) top.set_transient_for(self.parent_window) top.set_has_separator(False) top.vbox.set_spacing(5) label = gtk.Label('<span size="larger" weight="bold">%s</span>' % _("Organize Tags")) label.set_use_markup(True) top.vbox.pack_start(label, 0, 0, 5) box = gtk.HBox() top.vbox.pack_start(box, 1, 1, 5) name_titles = [ ('', NOSORT, 20, INTEGER), # Priority ('', NOSORT, 100), # Handle (_('Name'), NOSORT, 200), (_('Color'), NOSORT, 50, COLOR) ] self.namelist = gtk.TreeView() self.namemodel = ListModel(self.namelist, name_titles) slist = gtk.ScrolledWindow() slist.add_with_viewport(self.namelist) slist.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) box.pack_start(slist, 1, 1, 5) bbox = gtk.VButtonBox() bbox.set_layout(gtk.BUTTONBOX_START) bbox.set_spacing(6) up = gtk.Button(stock=gtk.STOCK_GO_UP) down = gtk.Button(stock=gtk.STOCK_GO_DOWN) add = gtk.Button(stock=gtk.STOCK_ADD) edit = gtk.Button(stock=gtk.STOCK_EDIT) remove = gtk.Button(stock=gtk.STOCK_REMOVE) up.connect('clicked', self.cb_up_clicked) down.connect('clicked', self.cb_down_clicked) add.connect('clicked', self.cb_add_clicked, top) edit.connect('clicked', self.cb_edit_clicked, top) remove.connect('clicked', self.cb_remove_clicked, top) top.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) top.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP) bbox.add(up) bbox.add(down) bbox.add(add) bbox.add(edit) bbox.add(remove) box.pack_start(bbox, 0, 0, 5) top.show_all() return top def cb_up_clicked(self, obj): """ Move the current selection up one row. """ row = self.namemodel.get_selected_row() self.namemodel.move_up(row) def cb_down_clicked(self, obj): """ Move the current selection down one row. """ row = self.namemodel.get_selected_row() self.namemodel.move_down(row) def cb_add_clicked(self, button, top): """ Create a new tag. """ tag = Tag() tag.set_priority(self.db.get_number_of_tags()) edit_dialog = EditTag(self.db, top, tag) edit_dialog.run() if tag.get_handle(): self.namemodel.add((tag.get_priority(), tag.get_handle(), tag.get_name(), tag.get_color())) def cb_edit_clicked(self, button, top): """ Edit the color of an existing tag. """ store, iter_ = self.namemodel.get_selected() if iter_ is None: return tag = self.db.get_tag_from_handle(store.get_value(iter_, 1)) edit_dialog = EditTag(self.db, top, tag) edit_dialog.run() store.set_value(iter_, 2, tag.get_name()) store.set_value(iter_, 3, tag.get_color()) def cb_remove_clicked(self, button, top): """ Remove the selected tag. """ store, iter_ = self.namemodel.get_selected() if iter_ is None: return tag_handle = store.get_value(iter_, 1) tag_name = store.get_value(iter_, 2) yes_no = QuestionDialog2( _("Remove tag '%s'?") % tag_name, _("The tag definition will be removed. " "The tag will be also removed from all objects in the database." ), _("Yes"), _("No")) prompt = yes_no.run() if prompt: fnc = { 'Person': (self.db.get_person_from_handle, self.db.commit_person), 'Family': (self.db.get_family_from_handle, self.db.commit_family), 'Event': (self.db.get_event_from_handle, self.db.commit_event), 'Place': (self.db.get_place_from_handle, self.db.commit_place), 'Source': (self.db.get_source_from_handle, self.db.commit_source), 'Repository': (self.db.get_repository_from_handle, self.db.commit_repository), 'MediaObject': (self.db.get_object_from_handle, self.db.commit_media_object), 'Note': (self.db.get_note_from_handle, self.db.commit_note) } links = [ link for link in self.db.find_backlink_handles(tag_handle) ] # Make the dialog modal so that the user can't start another # database transaction while the one removing tags is still running. pmon = progressdlg.ProgressMonitor( progressdlg.GtkProgressDialog, ("", self.parent_window, gtk.DIALOG_MODAL), popup_time=2) status = progressdlg.LongOpStatus(msg=_("Removing Tags"), total_steps=len(links), interval=len(links) // 20) pmon.add_op(status) msg = _('Delete Tag (%s)') % tag_name with DbTxn(msg, self.db) as trans: for classname, handle in links: status.heartbeat() obj = fnc[classname][0](handle) # get from handle obj.remove_tag(tag_handle) fnc[classname][1](obj, trans) # commit self.db.remove_tag(tag_handle, trans) self.__change_tag_priority(trans) self.namemodel.remove(iter_) status.end()
class SourceReferences(Gramplet): """ Displays the back references for an object. """ def init(self): self.gui.WIDGET = self.build_gui() self.gui.get_container_widget().remove(self.gui.textview) self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET) self.gui.WIDGET.show() def build_gui(self): """ Build the GUI interface. """ top = gtk.TreeView() titles = [(_('Type'), 0, 100), (_('Name'), 1, 100), ('', 2, 1), #hidden column for the handle ('', 3, 1)] #hidden column for non-localized object type self.model = ListModel(top, titles, event_func=self.cb_double_click) return top def display_backlinks(self, active_handle): """ Display the back references for an object. """ for classname, handle in self.dbstate.db.find_backlink_handles(active_handle): for classname, handle in self.dbstate.db.find_backlink_handles(handle): name = navigation_label(self.dbstate.db, classname, handle)[0] self.model.add((_(classname), name, handle, classname)) self.set_has_data(self.model.count > 0) def get_has_data(self, active_handle): """ Return True if the gramplet has data, else return False. """ if active_handle is None: return False for classname, handle in self.dbstate.db.find_backlink_handles(active_handle): for classname, handle in self.dbstate.db.find_backlink_handles(handle): return True return False def cb_double_click(self, treeview): """ Handle double click on treeview. """ (model, iter_) = treeview.get_selection().get_selected() if not iter_: return (objclass, handle) = (model.get_value(iter_, 3), model.get_value(iter_, 2)) edit_object(self.dbstate, self.uistate, objclass, handle) def db_changed(self): self.dbstate.db.connect('source-update', self.update) self.connect_signal('Source', self.update) def update_has_data(self): active_handle = self.get_active('Source') self.set_has_data(self.get_has_data(active_handle)) def main(self): active_handle = self.get_active('Source') self.model.clear() if active_handle: self.display_backlinks(active_handle) else: self.set_has_data(False)
def clearData(self): self.m_pModel = ListModel([]) self.setModel(self.m_pModel)
class UpdateAddons(ManagedWindow.ManagedWindow): def __init__(self, uistate, track, addon_update_list): self.title = _('Available Gramps Updates for Addons') ManagedWindow.ManagedWindow.__init__(self, uistate, track, self.__class__) glade = Glade("updateaddons.glade") self.update_dialog = glade.toplevel self.set_window(self.update_dialog, glade.get_object('title'), self.title) self.window.set_size_request(750, 400) apply_button = glade.get_object('apply') cancel_button = glade.get_object('cancel') select_all = glade.get_object('select_all') select_all.connect("clicked", self.select_all_clicked) select_none = glade.get_object('select_none') select_none.connect("clicked", self.select_none_clicked) apply_button.connect("clicked", self.install_addons) cancel_button.connect("clicked", self.close) self.list = ListModel( glade.get_object("list"), [ # name, click?, width, toggle { "name": _('Select'), "width": 60, "type": TOGGLE, "visible_col": 6, "editable": True }, # 0 selected? (_('Type'), 1, 180), # 1 new gramplet (_('Name'), 2, 200), # 2 name (version) (_('Description'), 3, 200), # 3 description ('', NOSORT, 0), # 4 url ('', NOSORT, 0), # 5 id { "name": '', "type": TOGGLE }, # 6 visible? bool ], list_mode="tree") pos = None addon_update_list.sort(key=lambda x: "%s %s" % (x[0], x[2]["t"])) last_category = None for (status, plugin_url, plugin_dict) in addon_update_list: count = get_count(addon_update_list, plugin_dict["t"]) category = _("%(adjective)s: %(addon)s") % { "adjective": status, "addon": _(plugin_dict["t"]) } if last_category != category: last_category = category node = self.list.add([ False, # initially selected? category, "", "", "", "", False ]) # checkbox visible? iter = self.list.add( [ False, # initially selected? "%s %s" % (status, _(plugin_dict["t"])), "%s (%s)" % (plugin_dict["n"], plugin_dict["v"]), plugin_dict["d"], plugin_url, plugin_dict["i"], True ], node=node) if pos is None: pos = iter if pos: self.list.selection.select_iter(pos) self.update_dialog.run() def build_menu_names(self, obj): return (self.title, "") def select_all_clicked(self, widget): """ Select all of the addons for download. """ self.list.model.foreach(update_rows, True) self.list.tree.expand_all() def select_none_clicked(self, widget): """ Select none of the addons for download. """ self.list.model.foreach(update_rows, False) self.list.tree.expand_all() def install_addons(self, obj): """ Process all of the selected addons. """ self.update_dialog.hide() model = self.list.model iter = model.get_iter_first() length = 0 while iter: iter = model.iter_next(iter) if iter: length += model.iter_n_children(iter) longop = LongOpStatus( _("Downloading and installing selected addons..."), length, 1, # total, increment-by can_cancel=True) pm = ProgressMonitor(GtkProgressDialog, ("Title", self.window, gtk.DIALOG_MODAL)) pm.add_op(longop) count = 0 if not config.get('behavior.do-not-show-previously-seen-updates'): # reset list config.get('behavior.previously-seen-updates')[:] = [] iter = model.get_iter_first() while iter: for rowcnt in range(model.iter_n_children(iter)): child = model.iter_nth_child(iter, rowcnt) row = [model.get_value(child, n) for n in range(6)] if longop.should_cancel(): break elif row[0]: # toggle on load_addon_file(row[4], callback=LOG.debug) count += 1 else: # add to list of previously seen, but not installed if row[5] not in config.get( 'behavior.previously-seen-updates'): config.get('behavior.previously-seen-updates').append( row[5]) longop.heartbeat() pm._get_dlg()._process_events() iter = model.iter_next(iter) if not longop.was_cancelled(): longop.end() if count: OkDialog( _("Done downloading and installing addons"), "%s %s" % (ngettext("%d addon was installed.", "%d addons were installed.", count) % count, _("You need to restart Gramps to see new views.")), self.window) else: OkDialog(_("Done downloading and installing addons"), _("No addons were installed."), self.window) self.close()
def __init__(self): super(GmailModule, self).__init__() self.scopes = ['https://mail.google.com/'] self.time_elapsed = 0 self.currentEmailList = ListModel(GmailModule.EmailObject) self.threadMessages = ListModel(GmailModule.EmailObject)
class ListView(QListView): ''' 自定义视图 ''' map_listview = [] # map_listview保存QListView对象和分组名称的对应关系 def __init__(self): ''' 一些初始设置 ''' super().__init__() self.m_pModel = ListModel() self.setModel(self.m_pModel) def contextMenuEvent(self, event): ''' 上下文菜单 ''' hitIndex = self.indexAt(event.pos()).column() # 返回鼠标指针相对于接收事件的小部件的位置 if hitIndex > -1: # 找到索引 pmenu = QMenu(self) pDeleteAct = QAction("删除", pmenu) pmenu.addAction(pDeleteAct) pDeleteAct.triggered.connect(self.deleteItemSlot) pSubMenu = QMenu("转移联系人至", pmenu) pmenu.addMenu(pSubMenu) for item_dic in self.map_listview: # 这里我们将每个分组名称取出,新建一个QAction对象,加入到pSubMenu当中。 pMoveAct = QAction(item_dic['groupname'], pmenu) pSubMenu.addAction(pMoveAct) pMoveAct.triggered.connect(self.move) # 点击这个每个分组的时候就会执行联系人转移分组操作,这里就是move()的调用。 pmenu.popup(self.mapToGlobal(event.pos())) # 显示菜单,以便动作QAction对象在指定的全局位置p处。这里的全局位置p是根据小部件的本地坐标转换为全局坐标的 def deleteItemSlot(self): ''' 删除联系人 ''' index = self.currentIndex().row() if index > -1: self.m_pModel.deleteItem(index) def setListMap(self, listview): ''' 将分组名称和QListView对象这个字典增加到map_listview数据列表中 ''' self.map_listview.append(listview) def addItem(self, pitem): ''' 新增一个联系人 ''' self.m_pModel.addItem(pitem) def move(self): ''' 实现联系人转移 ''' tolistview = self.find(self.sender().text()) # 点击的分组名称找到对应的QListView对象 if tolistview is self: prelistview = self.sender().text() QMessageBox.warning(self, "警告", "该联系人就在{},还怎么移动啊!".format(prelistview)) # 假设联系人就在将转移的分组,那我们就没有必要转移了 else: index = self.currentIndex().row() pItem = self.m_pModel.getItem(index) tolistview.addItem(pItem) self.m_pModel.deleteItem(index) # 否则我们首先要获得这个联系人,然后在将转移的分组中将这个联系人加上,原分组联系人删除 def find(self, pmenuname): ''' 找到分组对象 ''' for item_dic in self.map_listview: if item_dic['groupname'] == pmenuname: return item_dic['listview']