示例#1
0
 def tell_command(self, query=None):
     return [
         Item('Open config file...',
              arg='open|' + self.config_file,
              valid=True),
         Item('Open debug log...', arg='open|' + self.log_file, valid=True),
     ]
示例#2
0
    def tell_weather(self, ignored):
        '''Tell the current weather and a short forecast'''
        LOG.debug('telling weather')
        units = self.nest.scale.lower()

        def new_forecast(title, info):
            tcond = info['condition'].capitalize()
            thi = info['temp_high_' + units]
            tlo = info['temp_low_' + units]
            item = Item(u'%s: %s' % (title, tcond),
                        subtitle=u'High: {0:.1f}°{1},  '
                                 u'Low: {2:.1f}°{1}'.format(
                                     thi, units.upper(), tlo))
            return item

        data = self.nest.structure.weather
        conditions = data['current']['condition'].capitalize()
        temp = data['current']['temp_' + units]
        humidity = data['current']['humidity']

        items = []

        item = Item(u'Now: %s' % conditions)
        item.subtitle = u'{0:.1f}°{1},  {2:.0f}% humidity'.format(
                        temp, units.upper(), humidity)
        items.append(item)

        items.append(new_forecast('Today', data['forecast']['daily'][0]))
        items.append(new_forecast('Tomorrow', data['forecast']['daily'][1]))

        return items
示例#3
0
    def tell_weather(self, location, prefix=None):
        '''Tell the current conditions and forecast for a location'''

        location = location.strip()
        weather = self._get_weather(location)

        items = self._show_alert_information(weather)

        # conditions
        tu = 'F' if self.config['units'] == 'us' else 'C'
        title = u'Currently in {0}: {1}'.format(
            self.config['location']['short_name'],
            weather['current']['weather'].capitalize())
        subtitle = u'{0}°{1},  {2}% humidity'.format(
            int(round(weather['current']['temp'])), tu,
            int(round(weather['current']['humidity'])))
        if self.config['show_localtime']:
            subtitle += ', local time is {0}'.format(
                self._remotize_time().strftime(self.config['time_format']))
            if self.config['feelslike']:
                subtitle = u'Feels like ' + subtitle

        icon = self._get_icon(weather['current']['icon'])
        arg = SERVICES[self.config['service']]['lib'].get_forecast_url(
            location)
        items.append(
            Item(title, subtitle, icon=icon, valid=True, arg=clean_str(arg)))

        location = '{},{}'.format(self.config['location']['latitude'],
                                  self.config['location']['longitude'])

        # forecast
        days = self._get_days(weather)

        sunset = weather['info']['sunset']
        today_word = self._get_today_word(sunset).capitalize()

        for day in days:
            day_desc = self._get_day_desc(day['date'], today_word)
            title = u'{}: {}'.format(day_desc, day['conditions'].capitalize())
            subtitle = u'High: {}°{},  Low: {}°{}'.format(
                day['temp_hi'], tu, day['temp_lo'], tu)
            if 'precip' in day:
                subtitle += u',  Precip: {}%'.format(day['precip'])
            arg = SERVICES[self.config['service']]['lib'].get_forecast_url(
                location, day['date'])
            icon = self._get_icon(day['icon'])
            items.append(
                Item(title,
                     subtitle,
                     icon=icon,
                     arg=clean_str(arg),
                     valid=True))

        items.append(self._get_copyright_info(weather))
        return items
示例#4
0
    def tell_about(self, name, query='', prefix=None):
        import sys
        import json

        with open('update.json', 'rt') as uf:
            data = json.load(uf)
        items = [Item('Version: {0}'.format(data['version']))]
        py_ver = 'Python: {:08X}'.format(sys.hexversion)
        items.append(Item(py_ver))

        return items
示例#5
0
 def tell_start(self, query):
     LOG.info('adding a new time entry...')
     items = []
     desc = query.strip()
     if desc:
         items.append(
             Item('Creating timer "{0}"...'.format(desc),
                  arg='start|' + desc,
                  valid=True))
     else:
         items.append(Item('Waiting for description...'))
     return items
示例#6
0
 def _show_alert_information(self, weather):
     items = []
     if 'alerts' in weather:
         for alert in weather['alerts']:
             item = Item(alert['description'], icon='error.png')
             if alert['expires']:
                 item.subtitle = 'Expires at {}'.format(alert['expires'].strftime(
                     self.config['time_format']))
             if 'uri' in alert:
                 item.arg = clean_str(alert['uri'])
                 item.valid = True
             items.append(item)
     return items
示例#7
0
 def _show_alert_information(self, weather):
     items = []
     if 'alerts' in weather:
         for alert in weather['alerts']:
             item = Item(alert['description'], icon='error.png')
             if alert['expires']:
                 item.subtitle = 'Expires at {}'.format(
                     alert['expires'].strftime(self.config['time_format']))
             if 'uri' in alert:
                 item.arg = clean_str(alert['uri'])
                 item.valid = True
             items.append(item)
     return items
示例#8
0
 def tell_start(self, query):
     LOG.info('tell_start(%s)', query)
     items = []
     desc = query.strip()
     if desc:
         items.append(
             Item('Creating timer "{0}"...'.format(desc),
                  arg='start|' + desc,
                  valid=True))
         LOG.debug('created item %s', items[-1])
     else:
         items.append(Item('Waiting for description...'))
     return items
示例#9
0
    def tell_commands(self, query):
        LOG.info('telling cmd with "{0}"'.format(query))
        items = []

        items.append(
            Item('Open toggl.com',
                 arg='open|https://new.toggl.com/app',
                 subtitle='Open a browser tab for toggl.com',
                 valid=True))

        items.append(
            Item('Open the workflow config file',
                 arg='open|' + self.config_file,
                 subtitle='Change workflow options here, like the '
                 'debug log level',
                 valid=True))

        items.append(
            Item('Open the debug log',
                 arg='open|' + self.log_file,
                 subtitle='Open a browser tab for toggl.com',
                 valid=True))

        if self.config['use_notifier']:
            items.append(
                Item('Disable the menubar notifier',
                     subtitle='Exit and disable the menubar notifier',
                     arg='disable_notifier',
                     valid=True))
        else:
            items.append(
                Item('Enable the menubar notifier',
                     subtitle='Start and enable the menubar notifier',
                     arg='enable_notifier',
                     valid=True))

        items.append(
            Item('Clear the cache',
                 subtitle='Force a cache refresh on the next query',
                 arg='force_refresh',
                 valid=True))

        if 'api_key' in self.config:
            items.append(
                Item('Forget your API key',
                     subtitle='Forget your stored API key, allowing '
                     'you to change it',
                     arg='clear_key',
                     valid=True))

        if len(query.strip()) > 1:
            # there's a filter
            items = self.fuzzy_match_list(query.strip(),
                                          items,
                                          key=lambda t: t.title)
        if len(items) == 0:
            items.append(Item("Invalid command"))

        return items
示例#10
0
    def tell_location(self, query, prefix=None):
        items = []
        query = query.strip()

        if len(query) > 0:
            results = wunderground.autocomplete(query)
            for result in [r for r in results if r['type'] == 'city']:
                items.append(
                    Item(result['name'],
                         arg='location|' + result['name'],
                         valid=True))
        else:
            items.append(Item('Enter a location...'))

        return items
示例#11
0
 def _convert(self, query):
     query = query.strip()
     try:
         value, text = self.converter.convert(query)
     except Exception, e:
         LOG.exception('Error converting')
         if e.message.startswith('Parse error in query'):
             return [Item('Waiting for input...')]
         else:
             try:
                 int(e.message)
                 return [Item('Waiting for input...')]
             except:
                 pass
         raise e
示例#12
0
 def tell_feelslike(self, query, prefix=None):
     feelslike = self.config.get('feelslike', False)
     return [
         Item('Toggle whether to show "feels like" temperatures',
              subtitle='Current value is ' + str(feelslike).lower(),
              arg='feelslike',
              valid=True)
     ]
示例#13
0
    def tell_convert(self, query):
        '''Perform a simple conversion query.'''
        LOG.debug('called with query "%s"', query)

        try:
            return self._convert(query)
        except:
            return [Item('Waiting for input...')]
示例#14
0
    def tell_icons(self, ignored):
        items = []
        sets = [f for f in os.listdir('icons') if not f.startswith('.')]
        for iset in sets:
            uid = 'icons-{}'.format(iset)
            icon = 'icons/{}/{}.png'.format(iset, EXAMPLE_ICON)
            title = iset.capitalize()
            item = Item(title, uid=uid, icon=icon, arg=u'icons|' + iset, valid=True)

            info_file = os.path.join('icons', iset, 'info.json')
            if os.path.exists(info_file):
                with open(info_file, 'rt') as ifile:
                    info = json.load(ifile)
                    if 'description' in info:
                        item.subtitle = info['description']

            items.append(item)
        return items
示例#15
0
 def _get_copyright_info(self, weather):
     arg = SERVICES[self.config['service']]['url']
     time = weather['info']['time'].strftime(self.config['time_format'])
     return Item(LINE,
                 u'Fetched from {} at {}'.format(
                     SERVICES[self.config['service']]['name'], time),
                 icon='blank.png',
                 arg=arg,
                 valid=True)
示例#16
0
    def tell_target(self, temp):
        '''Tell the target temperature'''
        LOG.debug('telling target temperature')

        target = self.nest.target_temperature
        temp = temp.strip()
        temp = temp.strip('"')
        temp = temp.strip("'")
        units = self.nest.scale.upper()

        if temp:
            if self.nest.mode == 'range':
                temps = temp.split()
                if len(temps) != 2:
                    return [Item('Waiting for valid input...')]
                for t in temps:
                    if len(t) == 1 or len(t) > 2:
                        return [Item('Waiting for valid input...')]
                return [Item(u'Set temperature range to %.1f°%s - %.1f°%s' % (
                             float(temps[0]), units, float(temps[1]), units),
                             arg=temp, valid=True)]
            else:
                return [Item(u'Set temperature to %.1f°%s' % (float(temp),
                        units), arg=temp, valid=True)]
        else:
            if self.nest.mode == 'range':
                item = Item(
                    u'Target temperature range is %.1f°%s - '
                    u'%.1f°%s' % (target[0], units, target[1], units))
            else:
                item = Item(
                    u'Target temperature: %.1f°%s' % (target, units))

        if self.nest.mode == 'range':
            item.subtitle = (u'Enter a temperature range in °%s to update; '
                             u'use format "low high"' % units)
        else:
            item.subtitle = u'Enter a temperature in °%s to update' % units

        return [item]
示例#17
0
    def tell_icons(self, ignored, prefix=None):
        items = []
        sets = [f for f in os.listdir('icons') if not f.startswith('.')]
        for iset in sets:
            uid = 'icons-{}'.format(iset)
            icon = 'icons/{}/{}.png'.format(iset, EXAMPLE_ICON)
            title = iset.capitalize()
            item = Item(title,
                        uid=uid,
                        icon=icon,
                        arg=u'icons|' + iset,
                        valid=True)

            info_file = os.path.join('icons', iset, 'info.json')
            if os.path.exists(info_file):
                with open(info_file, 'rt') as ifile:
                    info = json.load(ifile)
                    if 'description' in info:
                        item.subtitle = info['description']

            items.append(item)
        return items
示例#18
0
    def tell_format(self, fmt, prefix=None):
        items = []
        now = datetime.now()

        if fmt:
            try:
                items.append(
                    Item(now.strftime(fmt), arg='format|' + fmt, valid=True))
            except:
                items.append(Item('Waiting for input...'))
            items.append(
                Item('Python time format syntax...',
                     arg='http://docs.python.org/2/library/'
                     'datetime.html#strftime-and-strptime-'
                     'behavior',
                     valid=True))
        else:
            for fmt in TIME_FORMATS:
                items.append(
                    Item(now.strftime(fmt), arg='format|' + fmt, valid=True))

        return items
示例#19
0
    def tell_units(self, arg, prefix=None):
        arg = arg.strip()

        items = [
            Item('US',
                 u'US units (°F, in, mph)',
                 arg='units|us',
                 autocomplete='options units US',
                 valid=True),
            Item('SI',
                 u'SI units (°C, cm, kph)',
                 arg='units|si',
                 autocomplete='options units SI',
                 valid=True)
        ]

        items = self.partial_match_list(arg, items, key=lambda t: t.title)

        if len(items) == 0:
            items.append(Item('Invalid units'))

        return items
示例#20
0
    def tell_status(self, ignore):
        '''Tell the Nest's overall status'''
        LOG.debug('telling status')

        temp = self.nest.temperature
        target = self.nest.target_temperature
        humidity = self.nest.humidity
        away = 'yes' if self.nest.structure.away else 'no'
        fan = self.nest.fan
        units = self.nest.scale.upper()
        item = Item(u'Temperature: %.1f°%s' % (temp, units))

        if self.nest.mode == 'range':
            target = u'Heat/cool to %.1f°%s - %.1f°%s' % (
                target[0], units, target[1], units)
        elif self.nest.mode == 'heat':
            target = u'Heating to %.1f°%s' % (target, units)
        else:
            target = u'Cooling to %.1f°%s' % (target, units)

        item.subtitle = u'%s    Humidity: %.1f%%    Fan: %s    Away: %s' % (
            target, humidity, fan, away)
        return [item]
示例#21
0
    def tell_on(self, query):
        '''Return info about entries over a span

        A span may be:
            - a single start date, which denotes a span from that date to now
            - one of {'today', 'yesterday', 'this week'}
            - a week day name
        '''
        query = query.strip()
        if not query:
            return [
                Item('Enter a date', subtitle='9/8, yesterday, monday, '
                     '...')
            ]
        return self.tell_query('', start=get_start(query), end=get_end(query))
示例#22
0
    def tell_since(self, query):
        '''Return info about entries since a time

        A time may be:
            - a date
            - one of {'today', 'yesterday', 'this week'}
        '''
        query = query.strip()
        if not query:
            return [
                Item('Enter a start time',
                     subtitle='This can be a time, '
                     'date, datetime, "yesterday", "tuesday", ...')
            ]
        return self.tell_query('', start=get_start(query))
示例#23
0
    def tell_days(self, days, prefix=None):
        if len(days) == 0:
            length = '{} day'.format(self.config['days'])
            if self.config['days'] != 1:
                length += 's'
            return [
                Item(
                    'Enter the number of forecast days to show...',
                    subtitle='Currently showing {} of forecast'.format(length))
            ]
        else:
            days = int(days)

            if days < 0 or days > 10:
                raise Exception('Value must be between 1 and 10')

            length = '{} day'.format(days)
            if days != 1:
                length += 's'
            return [
                Item('Show {} of forecast'.format(length),
                     arg='days|{0}'.format(days),
                     valid=True)
            ]
示例#24
0
    def tell_service(self, query, prefix=None):
        items = []
        query = query.strip()

        for svc in SERVICES.keys():
            items.append(
                Item(SERVICES[svc]['name'],
                     uid=svc,
                     arg='service|' + svc,
                     valid=True))

        if len(query) > 0:
            q = query.lower()
            items = [i for i in items if q in i.title.lower()]

        return items
示例#25
0
 def tell_help(self, query):
     items = []
     items.append(
         Item("Use '/' to list existing timers",
              subtitle='Type some text to filter the results'))
     items.append(
         Item("Use '<' to list timers started since a time",
              subtitle='9/2, 9/2/13, 2013-9-2T22:00-04:00, ...'))
     items.append(
         Item("Use '#' to list time spent on a particular date",
              subtitle='9/2, 9/2/13, 2013-9-2T22:00-04:00, ...'))
     items.append(
         Item("Use '+' to start a new timer",
              subtitle="Type a description after the '+'"))
     items.append(Item("Use '.' to stop the current timer"))
     items.append(
         Item("Use '>' to access other commands",
              subtitle='Enable menubar icon, go to toggl.com, '
              '...'))
     items.append(Item("Select an existing timer to toggle it"))
     return items
示例#26
0
 def tell_help(self, query):
     items = []
     items.append(
         Item("Use '/' to list existing timers",
              subtitle='Type some text to filter the results'))
     items.append(
         Item("Use '//' to force a cache refresh",
              subtitle='Data from Toggl is normally cached for '
              '{0} seconds'.format(CACHE_LIFETIME)))
     items.append(
         Item("Use '<' to list timers started since a time",
              subtitle='9/2, 9/2/13, 2013-9-2T22:00-04:00, ...'))
     items.append(
         Item("Use '@' to list time spent on a particular date",
              subtitle='9/2, 9/2/13, 2013-9-2T22:00-04:00, ...'))
     items.append(
         Item("Use '+' to start a new timer",
              subtitle="Type a description after the '+'"))
     items.append(
         Item("Use '>' to access other commands",
              subtitle='Enable menubar icon, go to toggl.com, '
              '...'))
     items.append(Item("Select an existing timer to toggle it"))
     return items
示例#27
0
class UnitsWorkflow(Workflow):
    def __init__(self):
        super(UnitsWorkflow, self).__init__()
        self.currencies_file = os.path.join(self.cache_dir, 'currencies.txt')
        self.load_currencies()
        self.separator = self.config.get('separator') or '>'
        self.precision = self.config.get('precision') or None
        self.config['separator'] = self.separator
        self.config['precision'] = self.precision
        self.converter = Converter(self.currencies_file,
                                   separator=self.separator,
                                   precision=self.precision)

    def load_currencies(self):
        import datetime

        lines = []
        last_refresh = None
        today = datetime.date.today()

        if os.path.exists(self.currencies_file):
            with open(self.currencies_file, 'rt') as cf:
                lines = cf.readlines()

        if len(lines) > 0 and lines[0].startswith('# date:'):
            last_refresh = lines[0].split(':')[1].strip()
            last_refresh = datetime.datetime.strptime(last_refresh,
                                                      '%Y-%m-%d').date()

        if not last_refresh or last_refresh != today:
            import yfinance
            rates = yfinance.get_rates(CURRENCIES)
            with open(self.currencies_file, 'wt') as cf:
                cf.write('# date: ' + today.strftime('%Y-%m-%d') + '\n')
                cf.write('USD = [currency] = usd\n')
                for k, v in rates.items():
                    cf.write('{0} = USD / {1} = {2}\n'.format(k, v, k.lower()))

    def _convert(self, query):
        query = query.strip()
        try:
            value, text = self.converter.convert(query)
        except Exception, e:
            LOG.exception('Error converting')
            if e.message.startswith('Parse error in query'):
                return [Item('Waiting for input...')]
            else:
                try:
                    int(e.message)
                    return [Item('Waiting for input...')]
                except:
                    pass
            raise e

        return [
            Item(text,
                 arg=str(value),
                 valid=True,
                 subtitle='Action this item to copy %s to the '
                 'clipboard' % value)
        ]
示例#28
0
    def tell_query(self, query, start=None, end=None):
        '''List entries that match a query.

        Note that an end time without a start time will be ignored.'''
        LOG.info('tell_query("{0}", start={1}, end={2})'.format(
            query, start, end))
        if not start:
            end = None

        needs_refresh = False
        query = query.strip()

        if self.cache.get('disable_cache', False):
            LOG.debug('cache is disabled')
            needs_refresh = True
        elif self.cache.get('time') and self.cache.get('time_entries'):
            last_load_time = self.cache.get('time')
            LOG.debug('last load was %s', last_load_time)
            import time
            now = int(time.time())
            if now - last_load_time > CACHE_LIFETIME:
                LOG.debug('automatic refresh')
                needs_refresh = True
        else:
            LOG.debug('cache is missing timestamp or data')
            needs_refresh = True

        if needs_refresh:
            LOG.debug('refreshing cache')

            try:
                all_entries = toggl.TimeEntry.all()
            except Exception:
                LOG.exception('Error getting time entries')
                raise Exception('Problem talking to toggl.com')

            import time
            self.cache['time'] = int(time.time())
            self.cache['time_entries'] = serialize_entries(all_entries)
        else:
            LOG.debug('using cached data')
            all_entries = deserialize_entries(self.cache['time_entries'])

        LOG.debug('%d entries', len(all_entries))

        if start:
            LOG.debug('filtering on start time %s', start)
            if end:
                LOG.debug('filtering on end time %s', end)
                all_entries = [
                    e for e in all_entries
                    if e.start_time < end and e.stop_time > start
                ]
            else:
                all_entries = [e for e in all_entries if e.stop_time > start]
            LOG.debug('filtered to %d entries', len(all_entries))

        efforts = {}

        # group entries with the same description into efforts (so as not to be
        # confused with Toggl tasks
        for entry in all_entries:
            if entry.description not in efforts:
                efforts[entry.description] = Effort(entry.description, start,
                                                    end)
            efforts[entry.description].add(entry)

        efforts = efforts.values()
        efforts = sorted(efforts,
                         reverse=True,
                         key=lambda e: e.newest_entry.start_time)

        items = []

        if start:
            if len(efforts) > 0:
                seconds = sum(e.seconds for e in efforts)
                LOG.debug('total seconds: %s', seconds)
                total_time = to_hours_str(seconds)

                if end:
                    item = Item('{0} hours on {1}'.format(
                        total_time,
                        start.date().strftime(DATE_FORMAT)),
                                subtitle=Item.LINE)
                else:
                    item = Item('{0} hours from {1}'.format(
                        total_time,
                        start.date().strftime(DATE_FORMAT)),
                                subtitle=Item.LINE)
            else:
                item = Item('Nothing to report')

            items.append(item)

        show_suffix = start or end

        for effort in efforts:
            item = Item(effort.description, valid=True)
            now = LOCALTZ.localize(datetime.datetime.now())

            newest_entry = effort.newest_entry
            if newest_entry.is_running:
                item.icon = 'running.png'
                started = newest_entry.start_time
                delta = to_approximate_time(now - started)

                seconds = effort.seconds
                total = ''
                if seconds > 0:
                    hours = to_hours_str(seconds, show_suffix=show_suffix)
                    total = ' ({0} hours total)'.format(hours)
                item.subtitle = 'Running for {0}{1}'.format(delta, total)
                item.arg = 'stop|{0}|{1}'.format(newest_entry.id,
                                                 effort.description)
            else:
                seconds = effort.seconds
                hours = to_hours_str(datetime.timedelta(seconds=seconds),
                                     show_suffix=show_suffix)

                if start:
                    item.subtitle = ('{0} hours'.format(hours))
                else:
                    stop = newest_entry.stop_time
                    if stop:
                        delta = to_approximate_time(now - stop, ago=True)
                    else:
                        delta = 'recently'
                    oldest = effort.oldest_entry
                    since = oldest.start_time
                    since = since.strftime('%m/%d')
                    item.subtitle = ('{0} hours since {1}, '
                                     'stopped {2}'.format(hours, since, delta))

                item.arg = 'continue|{0}|{1}'.format(newest_entry.id,
                                                     effort.description)

            items.append(item)

        if len(query.strip()) > 1:
            # there's a filter
            test = query[1:].strip()
            items = self.fuzzy_match_list(test, items, key=lambda t: t.title)

        if len(items) == 0:
            items.append(Item("Nothing found"))

        return items
示例#29
0
    def tell_query(self, query, start=None, end=None):
        '''List entries that match a query.

        Note that an end time without a start time will be ignored.'''
        LOG.info('tell_query("{0}", start={1}, end={2})'.format(
                 query, start, end))
        if not start:
            end = None

        needs_refresh = False
        query = query.strip()

        if self.cache.get('disable_cache', False):
            LOG.debug('cache is disabled')
            needs_refresh = True
        elif self.cache.get('time') and self.cache.get('time_entries'):
            last_load_time = self.cache.get('time')
            LOG.debug('last load was %s', last_load_time)
            import time
            now = int(time.time())
            if now - last_load_time > CACHE_LIFETIME:
                LOG.debug('automatic refresh')
                needs_refresh = True
        else:
            LOG.debug('cache is missing timestamp or data')
            needs_refresh = True

        if needs_refresh:
            LOG.debug('refreshing cache')

            try:
                all_entries = toggl.TimeEntry.all()
            except Exception:
                LOG.exception('Error getting time entries')
                raise Exception('Problem talking to toggl.com')

            import time
            self.cache['time'] = int(time.time())
            self.cache['time_entries'] = serialize_entries(all_entries)
        else:
            LOG.debug('using cached data')
            all_entries = deserialize_entries(self.cache['time_entries'])

        LOG.debug('%d entries', len(all_entries))

        if start:
            LOG.debug('filtering on start time %s', start)
            if end:
                LOG.debug('filtering on end time %s', end)
                all_entries = [e for e in all_entries if e.start_time < end
                               and e.stop_time > start]
            else:
                all_entries = [e for e in all_entries if e.stop_time > start]
            LOG.debug('filtered to %d entries', len(all_entries))

        efforts = {}

        # group entries with the same description into efforts (so as not to be
        # confused with Toggl tasks
        for entry in all_entries:
            if entry.description not in efforts:
                efforts[entry.description] = Effort(entry.description, start,
                                                    end)
            efforts[entry.description].add(entry)

        efforts = efforts.values()
        efforts = sorted(efforts, reverse=True,
                         key=lambda e: e.newest_entry.start_time)

        items = []

        if start:
            if len(efforts) > 0:
                seconds = sum(e.seconds for e in efforts)
                LOG.debug('total seconds: %s', seconds)
                total_time = to_hours_str(seconds)

                if end:
                    item = Item('{0} hours on {1}'.format(
                                total_time,
                                start.date().strftime(DATE_FORMAT)),
                                subtitle=Item.LINE)
                else:
                    item = Item('{0} hours from {1}'.format(
                                total_time,
                                start.date().strftime(DATE_FORMAT)),
                                subtitle=Item.LINE)
            else:
                item = Item('Nothing to report')

            items.append(item)

        show_suffix = start or end

        for effort in efforts:
            item = Item(effort.description, valid=True)
            now = LOCALTZ.localize(datetime.datetime.now())

            newest_entry = effort.newest_entry
            if newest_entry.is_running:
                item.icon = 'running.png'
                started = newest_entry.start_time
                delta = to_approximate_time(now - started)

                seconds = effort.seconds
                total = ''
                if seconds > 0:
                    hours = to_hours_str(seconds, show_suffix=show_suffix)
                    total = ' ({0} hours total)'.format(hours)
                item.subtitle = 'Running for {0}{1}'.format(delta, total)
                item.arg = 'stop|{0}|{1}'.format(newest_entry.id,
                                                 effort.description)
            else:
                seconds = effort.seconds
                hours = to_hours_str(datetime.timedelta(seconds=seconds),
                                     show_suffix=show_suffix)

                if start:
                    item.subtitle = ('{0} hours'.format(hours))
                else:
                    stop = newest_entry.stop_time
                    if stop:
                        delta = to_approximate_time(now - stop, ago=True)
                    else:
                        delta = 'recently'
                    oldest = effort.oldest_entry
                    since = oldest.start_time
                    since = since.strftime('%m/%d')
                    item.subtitle = ('{0} hours since {1}, '
                                     'stopped {2}'.format(hours, since, delta))

                item.arg = 'continue|{0}|{1}'.format(newest_entry.id,
                                                     effort.description)

            items.append(item)

        if len(query.strip()) > 1:
            # there's a filter
            test = query[1:].strip()
            items = self.fuzzy_match_list(test, items,
                                          key=lambda t: t.title)

        if len(items) == 0:
            items.append(Item("Nothing found"))

        return items
示例#30
0
 def _create_item(self, day_desc, content):
     title = u'{}: {}'.format(day_desc, content)
     icon = self._get_icon(ICON_NAME)
     return Item(title, icon=icon, valid=False)
示例#31
0
 def tell_config(self, query, prefix=None):
     return ([
         Item('Open the config file',
              arg='open|' + self.config_file,
              valid=True)
     ])
示例#32
0
 def tell_log(self, query, prefix=None):
     return [
         Item('Open the debug log', arg='open|' + self.log_file, valid=True)
     ]