about summary refs log tree commit diff stats
path: root/src/ui/chatwin.c
Commit message (Expand)AuthorAgeFilesLines
* Fix handling of encrypted carbonsPaul Fariello2019-06-211-4/+4
* Rename prof_message_t into ProfMessagePaul Fariello2019-06-201-1/+1
* Add prof_message_t to wrap all message attributesPaul Fariello2019-06-201-14/+16
* Add OMEMO policyPaul Fariello2019-04-171-0/+10
* Ensure encrypted carbon of own message are marked as encryptedPaul Fariello2019-04-101-0/+2
* Add OMEMO message encryption and decryptionPaul Fariello2019-04-101-0/+2
* Update copyright to include 2019Michael Vetter2019-01-221-1/+1
* Add preferences for tab displayJames Booth2018-03-091-4/+4
* Show name in statusbar tabs WIPJames Booth2018-03-081-6/+8
* Update copyrightJames Booth2018-01-211-1/+1
* Update CopyrightJames Booth2017-01-281-1/+1
* Allow chat prefix char to be set by pluginsJames Booth2017-01-201-1/+39
* Add titlebar encryption text to plugins apiJames Booth2017-01-191-0/+18
* Add win_print_historyJames Booth2016-10-151-1/+1
* Use win_print_outgoing for carbonsJames Booth2016-10-151-1/+1
* Rename win_print_incoming_message -> win_print_incomingJames Booth2016-10-151-2/+2
* Add win_print_outgoingJames Booth2016-10-151-1/+1
* Add win_printJames Booth2016-10-151-19/+19
* Remove win_vprintln_chJames Booth2016-10-151-12/+12
* Use win_printf_line where appropriateJames Booth2016-10-151-6/+6
* Add ch arg to win_printf_lineJames Booth2016-10-151-1/+1
* Use THEME_DEFAULTJames Booth2016-10-141-1/+1
* Add win_printf_lineJames Booth2016-10-141-1/+1
* Always use string format in win_printfJames Booth2016-10-121-4/+4
* Remove args from win_print_with_receiptJames Booth2016-10-111-1/+1
* Remove win_print, use win_printf insteadJames Booth2016-10-111-9/+9
* Rename win_vprint -> win_printfJames Booth2016-10-111-1/+1
* Send receipt request only when receiver supports featureJames Booth2016-08-181-2/+3
* Add resource to chat message plugin hooksJames Booth2016-08-101-2/+2
* Moved roster_list.cJames Booth2016-07-241-1/+1
* Moved chat_session.cJames Booth2016-07-241-1/+1
* Update GPL link in headersJames Booth2016-07-241-1/+1
* Move connection fulljid functionJames Booth2016-05-061-1/+1
* Rename jabber_ functionsJames Booth2016-05-061-1/+1
* Add session.cJames Booth2016-05-051-1/+1
* Removed #AX_PREFIX_CONFIG_HJames Booth2016-03-311-3/+3
* Add PGP decryption for incoming/outgoing carbonsJames Booth2016-03-221-2/+7
* Merge branch 'master' into plugins-cJames Booth2016-02-141-1/+1
|\
| * Updated copyrightJames Booth2016-02-141-1/+1
* | Added C plugin code from plugins branchJames Booth2016-02-141-6/+13
|/
* Don't show notification reminders for messages the user does not want notific...James Booth2016-02-041-3/+1
* Tidy notify_message()James Booth2016-02-041-14/+2
* Removed unused arg: prefs_do_chat_notify()James Booth2016-02-041-1/+1
* Implemented /console chat settingJames Booth2016-02-031-1/+1
* Added roster struct, create and destroy roster on connect/disconnectJames Booth2016-01-051-6/+11
* Tidy wins_create_summary()James Booth2015-11-291-0/+26
* Renamed /notify message -> /notify chatJames Booth2015-11-291-1/+1
* Added room specific notify settingsJames Booth2015-11-281-1/+1
* Only show reminder notifications when notifications are enabledJames Booth2015-11-251-2/+6
* Implemented regular chat notify triggersJames Booth2015-11-251-11/+1
o">= False class Loadable(object): paused = False progressbar_supported = False def __init__(self, gen, descr): self.load_generator = gen self.description = descr self.percent = 0 def get_description(self): return self.description def pause(self): self.paused = True def unpause(self): try: del self.paused except: pass def destroy(self): pass class CopyLoader(Loadable, FileManagerAware): progressbar_supported = True def __init__(self, copy_buffer, do_cut=False, overwrite=False): self.copy_buffer = tuple(copy_buffer) self.do_cut = do_cut self.original_copy_buffer = copy_buffer self.original_path = self.fm.thistab.path self.overwrite = overwrite self.percent = 0 if self.copy_buffer: self.one_file = self.copy_buffer[0] Loadable.__init__(self, self.generate(), 'Calculating size...') def _calculate_size(self, step): from os.path import join size = 0 stack = [f.path for f in self.copy_buffer] while stack: fname = stack.pop() if os.path.isdir(fname): stack.extend([join(fname, item) for item in os.listdir(fname)]) else: try: fstat = os.stat(fname) except: continue size += max(step, math.ceil(fstat.st_size / step) * step) return size def generate(self): from ranger.ext import shutil_generatorized as shutil_g if self.copy_buffer: # TODO: Don't calculate size when renaming (needs detection) bytes_per_tick = shutil_g.BLOCK_SIZE size = max(1, self._calculate_size(bytes_per_tick)) bar_tick = 100.0 / (float(size) / bytes_per_tick) if self.do_cut: self.original_copy_buffer.clear() if len(self.copy_buffer) == 1: self.description = "moving: " + self.one_file.path else: self.description = "moving files from: " + self.one_file.dirname for f in self.copy_buffer: for _ in shutil_g.move(src=f.path, dst=self.original_path, overwrite=self.overwrite): self.percent += bar_tick yield else: if len(self.copy_buffer) == 1: self.description = "copying: " + self.one_file.path else: self.description = "copying files from: " + self.one_file.dirname for f in self.copy_buffer: if os.path.isdir(f.path): for _ in shutil_g.copytree(src=f.path, dst=os.path.join(self.original_path, f.basename), symlinks=True, overwrite=self.overwrite): self.percent += bar_tick yield else: for _ in shutil_g.copy2(f.path, self.original_path, symlinks=True, overwrite=self.overwrite): self.percent += bar_tick yield cwd = self.fm.get_directory(self.original_path) cwd.load_content() class CommandLoader(Loadable, SignalDispatcher, FileManagerAware): """ Run an external command with the loader. Output from stderr will be reported. Ensure that the process doesn't ever ask for input, otherwise the loader will be blocked until this object is removed from the queue (type ^C in ranger) """ finished = False process = None def __init__(self, args, descr, silent=False, read=False): SignalDispatcher.__init__(self) Loadable.__init__(self, self.generate(), descr) self.args = args self.silent = silent self.read = read self.stdout_buffer = "" def generate(self): null = open(os.devnull, 'r') self.process = process = Popen(self.args, stdout=PIPE, stderr=PIPE, stdin=null) self.signal_emit('before', process=process, loader=self) if self.silent and not self.read: while process.poll() is None: yield sleep(0.03) else: py3 = sys.version >= '3' selectlist = [] if self.read: selectlist.append(process.stdout) if not self.silent: selectlist.append(process.stderr) while process.poll() is None: yield try: rd, _, __ = select.select(selectlist, [], [], 0.03) if rd: rd = rd[0] if rd == process.stderr: read = rd.readline() if py3: read = safeDecode(read) if read: self.fm.notify(read, bad=True) elif rd == process.stdout: read = rd.read(512) if py3: read = safeDecode(read) if read: self.stdout_buffer += read except select.error: sleep(0.03) if not self.silent: for l in process.stderr.readlines(): if py3: l = safeDecode(l) self.fm.notify(l, bad=True) if self.read: read = process.stdout.read() if py3: read = safeDecode(read) self.stdout_buffer += read null.close() self.finished = True self.signal_emit('after', process=process, loader=self) def pause(self): if not self.finished and not self.paused: try: self.process.send_signal(20) except: pass Loadable.pause(self) self.signal_emit('pause', process=self.process, loader=self) def unpause(self): if not self.finished and self.paused: try: self.process.send_signal(18) except: pass Loadable.unpause(self) self.signal_emit('unpause', process=self.process, loader=self) def destroy(self): self.signal_emit('destroy', process=self.process, loader=self) if self.process: self.process.kill() def safeDecode(string): try: return string.decode("utf-8") except (UnicodeDecodeError): if HAVE_CHARDET: return string.decode(chardet.detect(string)["encoding"]) else: return "" class Loader(FileManagerAware): seconds_of_work_time = 0.03 throbber_chars = r'/-\|' throbber_paused = '#' paused = False def __init__(self): self.queue = deque() self.item = None self.load_generator = None self.throbber_status = 0 self.rotate() self.old_item = None def rotate(self): """Rotate the throbber""" # TODO: move all throbber logic to UI self.throbber_status = \ (self.throbber_status + 1) % len(self.throbber_chars) self.status = self.throbber_chars[self.throbber_status] def add(self, obj): """ Add an object to the queue. It should have a load_generator method. """ while obj in self.queue: self.queue.remove(obj) self.queue.appendleft(obj) if self.paused: obj.pause() else: obj.unpause() def move(self, _from, to): try: item = self.queue[_from] except IndexError: return del self.queue[_from] if to == 0: self.queue.appendleft(item) if _from != 0: self.queue[1].pause() elif to == -1: self.queue.append(item) else: raise NotImplementedError def remove(self, item=None, index=None): if item is not None and index is None: for i, test in enumerate(self.queue): if test == item: index = i break else: return if index is not None: if item is None: item = self.queue[index] if hasattr(item, 'unload'): item.unload() item.destroy() del self.queue[index] if item.progressbar_supported: self.fm.ui.status.request_redraw() def pause(self, state): """ Change the pause-state to 1 (pause), 0 (no pause) or -1 (toggle) """ if state == -1: state = not self.paused elif state == self.paused: return self.paused = state if not self.queue: return if state: self.queue[0].pause() else: self.queue[0].unpause() def work(self): """ Load items from the queue if there are any. Stop after approximately self.seconds_of_work_time. """ if self.paused: self.status = self.throbber_paused return while True: # get the first item with a proper load_generator try: item = self.queue[0] if item.load_generator is None: self.queue.popleft() else: break except IndexError: return item.unpause() self.rotate() if item != self.old_item: if self.old_item: self.old_item.pause() self.old_item = item item.unpause() end_time = time() + self.seconds_of_work_time try: while time() < end_time: next(item.load_generator) if item.progressbar_supported: self.fm.ui.status.request_redraw() except StopIteration: self._remove_current_process(item) except Exception as err: self.fm.notify(err) self._remove_current_process(item) def _remove_current_process(self, item): item.load_generator = None self.queue.remove(item) if item.progressbar_supported: self.fm.ui.status.request_redraw() def has_work(self): """Is there anything to load?""" return bool(self.queue) def destroy(self): while self.queue: self.queue.pop().destroy()