From: Florian Schweikert Date: Wed, 15 Feb 2012 02:18:14 +0000 (+0100) Subject: Departure object changes, tests, small fix X-Git-Url: http://vcs.maemo.org/git/?p=pywienerlinien;a=commitdiff_plain;h=40c42351349747c16df30d710f6490d5cb52af23 Departure object changes, tests, small fix save deltatime for all input types, calculate and save departure datetime use assert-is_instance in tests set gstation at last value in qml, should activate refresh --- diff --git a/gotovienna-qml b/gotovienna-qml index 2ba243e..d2dc8fa 100755 --- a/gotovienna-qml +++ b/gotovienna-qml @@ -151,14 +151,37 @@ class Gui(QObject): threading.Thread(target=load_async).start() def map_departure(self, dep): + """ prepare departure list for qml gui + """ dep['lowfloor'] = 1 if dep['lowfloor'] else 0 - if type(dep['time']) == time: - dep['time'] = dep['time'].strftime('%H:%M') + dep['realtime'] = 1 if dep['realtime'] else 0 + dep['time'] = dep['ftime'] return dep departuresLoaded = Signal() @Slot(str) + def load_departures_test(self, **args): + """ valid args combinations + station + line, station + """ + def load_async(): + if args.has_key('station'): + if args.has_key('line'): + self.current_departures = map(self.map_departure, \ + self.itip.get_departures(args['line'], args['station'])) + #print self.current_departures + self.departuresLoaded.emit() + else: + self.current_departures = map(self.map_departure, \ + sort_departures(self.itip.get_departures_by_station(station))) + else: + raise KeyError('Missing valid argument combination') + + threading.Thread(target=load_async).start() + + @Slot(str) def load_departures(self, url): def load_async(): self.current_departures = map(self.map_departure, \ diff --git a/gotovienna/realtime.py b/gotovienna/realtime.py index 7bb2773..ad43db2 100644 --- a/gotovienna/realtime.py +++ b/gotovienna/realtime.py @@ -3,8 +3,10 @@ from gotovienna.BeautifulSoup import BeautifulSoup #from urllib2 import urlopen from urllib import quote_plus +# Use urlopen proxy for fake user agent from UrlOpener import urlopen from datetime import time, datetime, timedelta +import datetime as date import re import collections from errors import LineNotFoundError, StationNotFoundError @@ -20,45 +22,25 @@ class Departure(dict): self['line'] = line self['station'] = station self['direction'] = direction - self['time'] = time - self['lowfloor'] = lowfloor - - def __getitem__(self, *args, **kwargs): - if args[0] == 'ftime': - # string representation of time/minutes - return self.ftime - elif args[0] == 'deltatime': - # minutes - return self.departure_deltatime - elif args[0] == 'atime': - # time object - return self.departure_time - return dict.__getitem__(self, *args, **kwargs) - - @property - def departure_time(self): - """ return time object of departure time - """ - if type(self['time']) == time: - return self['time'] + now = datetime.now() + if type(time) == date.time: + time = make_datetime(now, time) + if type(time) == datetime: + # FIXME convert in ModelList + self['realtime'] = False + self['time'] = (time - now).seconds/60 + self['departure'] = time + elif type(time) == int: + # FIXME convert in ModelList + self['realtime'] = True + self['time'] = time + self['departure'] = now + timedelta(minutes=self['time']) else: - return (datetime.now() + timedelta(0, self['time']) * 60).time() + raise ValueError('Wrong type: time') - @property - def departure_deltatime(self): - """ return int representing minutes until departure - """ - if type(self['time']) == int: - return self['time'] - else: - raise NotImplementedError() - - @property - def ftime(self): - if type(self['time']) == int: - return str(self['time']) - elif type(self['time']) == time: - return self['time'].strftime('%H:%M') + # FIXME convert in ModelList + self['ftime'] = str(self['time']) + self['lowfloor'] = lowfloor class ITipParser: def __init__(self): @@ -263,7 +245,7 @@ class ITipParser: t = tim.strip(' ').split(':') if len(t) == 2 and all(map(lambda x: x.isdigit(), t)): t = map(int, t) - d['time'] = time(*t) + d['time'] = make_datetime(datetime.now(), time(*t)) else: # Unexpected content #TODO replace with logger @@ -274,7 +256,7 @@ class ITipParser: return dep def get_departures(self, url): - """ Get list of next departures as Departure object + """ Get list of next departures as Departure objects """ #TODO parse line name and direction for station site parsing @@ -301,7 +283,11 @@ class ITipParser: sleep(0.5) - + def get_departures_test(self, line, station): + """ replacement for get_departure + hide url in higher levels :) + """ + raise NotImplementedError UBAHN, TRAM, BUS, NIGHTLINE, OTHER = range(5) @@ -361,4 +347,17 @@ def categorize_lines(lines): lines.sort(key=get_line_sort_key) return [(LINE_TYPE_NAMES[key], categorized_lines[key]) - for key in sorted(categorized_lines)] + for key in sorted(categorized_lines)] + +def make_datetime(date, time): + """ Ugly workaround, immutable datetime ftw -.- + If + """ + if date.hour > time.hour: + date = date + timedelta(1) + return datetime(year=date.year, + month=date.month, + day=date.day, + hour=time.hour, + minute=time.minute, + second=time.second) diff --git a/gotovienna/tests/departures.py b/gotovienna/tests/departures.py index 9da88d1..0047cff 100644 --- a/gotovienna/tests/departures.py +++ b/gotovienna/tests/departures.py @@ -1,4 +1,4 @@ -from nose.tools import assert_equal +from nose.tools import assert_equal, assert_is_instance import sys import os from datetime import time, datetime @@ -34,12 +34,12 @@ def test_sort(): def test_atime(): for dep in departures: - assert_equal(time, type(dep['atime'])) + assert_is_instance(dep['departure'], datetime) def test_ftime(): for dep in departures: - assert_equal(str, type(dep['ftime'])) + assert_is_instance(dep['ftime'], str) def test_deltatime(): for dep in departures: - assert_equal(int, type(dep['deltatime'])) + assert_is_instance(dep['time'], int) diff --git a/gotovienna/tests/realtime.py b/gotovienna/tests/realtime.py index 0d3b08a..35dd9e0 100644 --- a/gotovienna/tests/realtime.py +++ b/gotovienna/tests/realtime.py @@ -1,13 +1,22 @@ # -*- coding: utf-8 -*- -from nose.tools import assert_equal, assert_true, assert_false +from nose.tools import assert_equal, assert_true, assert_false, assert_is_instance import sys import os -from datetime import time +from datetime import datetime sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) DATAPATH = os.path.join(os.path.dirname(__file__), 'data') +# bananas for the monkey +class datetime_static(datetime): + @classmethod + def now(cls): + return datetime(2000, 1, 1, 11, 50) + +from gotovienna import realtime +realtime.datetime = datetime_static from gotovienna.realtime import * +# parser = ITipParser() @@ -22,7 +31,7 @@ stations2 = open(os.path.join(DATAPATH, 'stations2.html'), 'r').read() parsed_lines = parser.parse_lines(lines) def test_lines(): - assert_equal(dict, type(parsed_lines)) + assert_is_instance(parsed_lines, dict) assert_true(parsed_lines) def test_line_amount(): @@ -65,14 +74,14 @@ def test_departures_by_station_lowfloor(): def test_departures_by_station_datetime(): dep = parser.parse_departures_by_station(stationbased) - assert_equal(int, type(dep[13]['time'])) - assert_equal(time, type(dep[14]['time'])) + assert_is_instance(dep[13]['time'], int) + assert_is_instance(dep[14]['departure'], datetime) assert_equal(4, dep[3]['time']) assert_equal(2, dep[4]['time']) assert_equal(18, dep[13]['time']) assert_equal('59A', dep[-4]['line']) assert_equal('WLB', dep[-1]['line']) - assert_equal(time(13, 5), dep[14]['time']) + assert_equal(datetime(2000, 1, 1, 13, 5), dep[14]['departure']) def test_departures(): dep = parser.parse_departures(line_station) diff --git a/gotovienna/tests/update.py b/gotovienna/tests/update.py new file mode 100644 index 0000000..64bead4 --- /dev/null +++ b/gotovienna/tests/update.py @@ -0,0 +1,19 @@ +from nose.tools import assert_true, assert_false +import sys +from os import path + +DATA = path.join(path.dirname(__file__), 'data') +HASHFILENAME = 'hashtestfile' + +with open(path.join(DATA, HASHFILENAME + '.md5')) as f: + HASH = f.read() + +sys.path.insert(0, path.dirname(path.dirname(__file__))) +from gotovienna.update import compare_hash + +def test_hash_equal(): + assert_true(compare_hash(HASH, path.join(DATA, HASHFILENAME))) + +def test_hash_not_equal(): + assert_false(compare_hash('GG' + HASH[2:], path.join(DATA, HASHFILENAME))) + diff --git a/gotovienna/utils.py b/gotovienna/utils.py index 2a15f6f..51940a6 100644 --- a/gotovienna/utils.py +++ b/gotovienna/utils.py @@ -10,7 +10,7 @@ def inblue(x): return '\033[94m' + x + '\033[0m' def sort_departures(dep): - print 'sorting ...' - d = sorted(dep, lambda x, y: cmp(x['atime'], y['atime'])) - print map(lambda x: x['atime'], d) + #print 'sorting ...' + d = sorted(dep, lambda x, y: cmp(x['departure'], y['departure'])) + #print map(lambda x: x['departure'], d) return d diff --git a/qml/MainPage.qml b/qml/MainPage.qml index 4d1947b..16090f0 100644 --- a/qml/MainPage.qml +++ b/qml/MainPage.qml @@ -27,13 +27,13 @@ Page { function showNearby() { console.log("show nearby") - var stations = nearbyStations - stationSelectorModel.clear() + var stations = nearbyStations; + stationSelectorModel.clear(); for (var idx in stations) { - stationSelectorModel.append({'name': stations[idx]}) + stationSelectorModel.append({'name': stations[idx]}); } - stationSelector.open() + stationSelector.open(); } Text { @@ -98,11 +98,11 @@ Page { onAccepted: { realtimeResult.isStation = true - realtimeResult.gstation = stationSelectorModel.get(selectedIndex).name realtimeResult.gline = '' realtimeResult.sourceUrl = '' gline.text = '' gstation.text = stationSelectorModel.get(selectedIndex).name + realtimeResult.gstation = stationSelectorModel.get(selectedIndex).name console.log('station to get: ' + realtimeResult.gstation) } } @@ -185,14 +185,13 @@ Page { gstation.text = stationSheet.currentStation realtimeResult.gline = stationSheet.currentLine - realtimeResult.gstation = stationSheet.currentStation realtimeResult.gdirection = stationSheet.currentDirection realtimeResult.isStation = false - realtimeResult.sourceUrl = itip.get_directions_url(stationSheet.currentLine, stationSheet.currentDirection, stationSheet.currentStation) - console.log('url to get: ' + realtimeResult.sourceUrl) + realtimeResult.gstation = stationSheet.currentStation + + console.debug('url to get: ' + realtimeResult.sourceUrl) realtimeResult.refresh() - } } diff --git a/qml/MapView.qml b/qml/MapView.qml new file mode 100644 index 0000000..ad52fdf --- /dev/null +++ b/qml/MapView.qml @@ -0,0 +1,35 @@ +import QtQuick 1.1 +import Qt 4.7 +import QtMobility.location 1.2 +import com.nokia.meego 1.0 + +Page { + tools: mapTools + + ToolBarLayout { + id: mapTools + x: 0 + y: 0 + ToolIcon { iconId: "toolbar-back"; onClicked: { menu.close(); pageStack.pop(null,false); } } + } + + Map { + id: map + plugin : Plugin { + name : "nokia" + } + + anchors.fill: parent + size.width: parent.width + size.height: parent.height + zoomLevel: 7 + //center: positionSource.position.coordinate + //objects: t_data.mapObjectsList + + + onZoomLevelChanged: { + console.log("Zoom changed") + } + + } +} diff --git a/qml/ResultRealtime.qml b/qml/ResultRealtime.qml index bf8e695..1ec034a 100644 --- a/qml/ResultRealtime.qml +++ b/qml/ResultRealtime.qml @@ -17,13 +17,13 @@ Item { function refresh() { busy = true - console.log('refreshing') + console.debug('refreshing') if (isStation) { - console.log('station based') + console.debug('station based') itip.load_station_departures(gstation) } else { - console.log('one line') + console.debug('one line') itip.load_departures(sourceUrl) } } @@ -33,6 +33,7 @@ Item { } onGstationChanged: { + console.debug('gstation changed') refresh() } diff --git a/qml/Settings.qml b/qml/Settings.qml index 6bf0d49..87f7f4f 100644 --- a/qml/Settings.qml +++ b/qml/Settings.qml @@ -22,6 +22,10 @@ Page { flickableDirection: Flickable.VerticalFlick Component.onCompleted: { + var updateAvailable = config.checkStationsUpdate(); + if (updateAvailable) { + btnUpdate.color = "green" + } } Column { @@ -53,13 +57,18 @@ Page { onCheckedChanged: { var gps = config.setGpsEnabled(checked); - if(gps !== '') { + if (gps !== '') { // Unable to set config console.log(gps); checked=!checked; } else { positionSource.active = checked; } + if (checked) { + positionSource.start(); + } else { + positionSource.stop(); + } } } }