def __init__(self, bbclient, config, parent=None): super(HistoryWidget, self).__init__(parent) self.bbclient = bbclient self.config = config self.track_list = [] self.list = QListWidget(self) self.list.setUniformItemSizes(True) self.list.setSelectionMode(QListWidget.ExtendedSelection) self.list.currentRowChanged.connect(self._onRowChanged) self.delete_btn = QPushButton(QIcon(resource_path('img/delete.png')), '', self) self.save_btn = QPushButton(QIcon(resource_path('img/save.png')), '', self) self.upload_btn = QPushButton(QIcon(resource_path('img/upload.png')), '', self) for i, w in enumerate((self.delete_btn, self.save_btn, self.upload_btn)): w.setIconSize(QSize(22, 22)) if i < 1: w.setMinimumSize(32, 32) w.setMaximumSize(32, 32) else: w.setMinimumSize(58, 32) w.setMaximumSize(58, 32) save_menu = QMenu('Export tracks', self) act = save_menu.addAction('Save as TCX') act.triggered.connect(self._onSaveAsTCX) act = save_menu.addAction('Save as BDX (Bryton GPX extension)') act.triggered.connect(self._onSaveAsBDX) self.save_btn.setMenu(save_menu) upload_menu = QMenu('Upload tracks', self) act = upload_menu.addAction(QIcon(resource_path('img/strava-icon.png')), 'Upload to Strava.com') act.triggered.connect(self._onUploadStrava) act = upload_menu.addAction(QIcon(resource_path('img/bryton-icon.png')), 'Upload to Brytonsport.com') act.triggered.connect(self._onUploadBrytonSport) self.upload_btn.setMenu(upload_menu) self.delete_btn.clicked.connect(self._onDeleteTracks) self._createLayout() self.message_overlay = MessageWidget(self) self.message_overlay.setLoading('Loading tracklist') bbclient.refreshingTrackList.connect(self.message_overlay.show)
def __init__(self, config, parent=None): super(MainWindow, self).__init__(parent) self.bbclient = BrytonClient(parent=self, server_host=config.get('server_host')) self.history_list_widget = HistoryWidget(self.bbclient, config, self) self.device_info_widget = DeviceInfoWidget(self) self.track_summary_widget = TrackSummaryWidget(self) self.track_tabs = QTabWidget(self) self.track_tabs.setMaximumWidth(200) self.track_tabs.addTab(self.history_list_widget, 'History') self.history_list_widget.currentTrackChanged.connect(self._onHistoryTrackChanged) self.bb_version = QLabel('', self) self.bb_version.setAlignment(Qt.AlignRight) self.bb_version.setContentsMargins(0, 0, 3, 0) self._createLayout() self.message_overlay = MessageWidget(self) self.message_overlay.setLoading('Connecting to BrytonBridge') self.message_overlay.retryClicked.connect(self._onRetry) self.bbclient.statusMessage.connect(self.message_overlay.setLoading) self.bbclient.connected.connect(self._onConnected) self.bbclient.deviceOffline.connect(self._onDeviceOffline) self.bbclient.deviceReady.connect(self._onDeviceReady) self.bbclient.trackListReady.connect(self._onTrackListReady) self.bbclient.error.connect(self._onError) self.bbclient.BBVersion.connect(self._onBBVersion) self.bbclient.start()
class MainWindow(QWidget): def __init__(self, config, parent=None): super(MainWindow, self).__init__(parent) self.bbclient = BrytonClient(parent=self, server_host=config.get('server_host')) self.history_list_widget = HistoryWidget(self.bbclient, config, self) self.device_info_widget = DeviceInfoWidget(self) self.track_summary_widget = TrackSummaryWidget(self) self.track_tabs = QTabWidget(self) self.track_tabs.setMaximumWidth(200) self.track_tabs.addTab(self.history_list_widget, 'History') self.history_list_widget.currentTrackChanged.connect(self._onHistoryTrackChanged) self.bb_version = QLabel('', self) self.bb_version.setAlignment(Qt.AlignRight) self.bb_version.setContentsMargins(0, 0, 3, 0) self._createLayout() self.message_overlay = MessageWidget(self) self.message_overlay.setLoading('Connecting to BrytonBridge') self.message_overlay.retryClicked.connect(self._onRetry) self.bbclient.statusMessage.connect(self.message_overlay.setLoading) self.bbclient.connected.connect(self._onConnected) self.bbclient.deviceOffline.connect(self._onDeviceOffline) self.bbclient.deviceReady.connect(self._onDeviceReady) self.bbclient.trackListReady.connect(self._onTrackListReady) self.bbclient.error.connect(self._onError) self.bbclient.BBVersion.connect(self._onBBVersion) self.bbclient.start() # self.message_overlay.hide() def _onConnected(self): self.message_overlay.setMessage('Searching for device') def _onDeviceReady(self): self.device_info_widget.setDeviceInfo(self.bbclient.dev_state) self.message_overlay.hide() def _onDeviceOffline(self): self.message_overlay.setDisconnected('Please connect your device') self.message_overlay.show() def _onError(self, msg): self.message_overlay.setError(msg) self.message_overlay.retry.show() self.message_overlay.show() def _onRetry(self): self.message_overlay.retry.hide() self.bbclient.reset() self.bbclient.start() def _onBBVersion(self, version): if version in TESTED_VERSIONS: self.bb_version.hide() self.bb_version.setText('BrytonBridge version <font color="green">{}</font>'.format(version)) else: self.bb_version.show() self.bb_version.setText('BrytonBridge version <font color="red"><b>{}</b></font>'.format(version)) self.bb_version.setToolTip('You are using an untested version of BrytonBridge') def _onTrackListReady(self): self.tracks = tracks = self.bbclient.track_list self.history_list_widget.setTrackList(tracks, self.bbclient.dev_state) def _onHistoryTrackChanged(self, track): self.track_summary_widget.setTrack(track) def resizeEvent(self, event): self.message_overlay.resize(event.size()) super(MainWindow, self).resizeEvent(event) def _createLayout(self): la = QVBoxLayout() la.addWidget(self.bb_version) l = QHBoxLayout() l.addWidget(self.track_tabs, 0) v = QVBoxLayout() group = QGroupBox('Device', self) l2 = QHBoxLayout() l2.addWidget(self.device_info_widget) group.setLayout(l2) v.addWidget(group) group = QGroupBox('Track Summary', self) l2 = QHBoxLayout() l2.addWidget(self.track_summary_widget) group.setLayout(l2) v.addWidget(group, 1) l.addLayout(v, 1) la.addLayout(l) self.setLayout(la)
class HistoryWidget(QWidget): currentTrackChanged = pyqtSignal(dict) def __init__(self, bbclient, config, parent=None): super(HistoryWidget, self).__init__(parent) self.bbclient = bbclient self.config = config self.track_list = [] self.list = QListWidget(self) self.list.setUniformItemSizes(True) self.list.setSelectionMode(QListWidget.ExtendedSelection) self.list.currentRowChanged.connect(self._onRowChanged) self.delete_btn = QPushButton(QIcon(resource_path('img/delete.png')), '', self) self.save_btn = QPushButton(QIcon(resource_path('img/save.png')), '', self) self.upload_btn = QPushButton(QIcon(resource_path('img/upload.png')), '', self) for i, w in enumerate((self.delete_btn, self.save_btn, self.upload_btn)): w.setIconSize(QSize(22, 22)) if i < 1: w.setMinimumSize(32, 32) w.setMaximumSize(32, 32) else: w.setMinimumSize(58, 32) w.setMaximumSize(58, 32) save_menu = QMenu('Export tracks', self) act = save_menu.addAction('Save as TCX') act.triggered.connect(self._onSaveAsTCX) act = save_menu.addAction('Save as BDX (Bryton GPX extension)') act.triggered.connect(self._onSaveAsBDX) self.save_btn.setMenu(save_menu) upload_menu = QMenu('Upload tracks', self) act = upload_menu.addAction(QIcon(resource_path('img/strava-icon.png')), 'Upload to Strava.com') act.triggered.connect(self._onUploadStrava) act = upload_menu.addAction(QIcon(resource_path('img/bryton-icon.png')), 'Upload to Brytonsport.com') act.triggered.connect(self._onUploadBrytonSport) self.upload_btn.setMenu(upload_menu) self.delete_btn.clicked.connect(self._onDeleteTracks) self._createLayout() self.message_overlay = MessageWidget(self) self.message_overlay.setLoading('Loading tracklist') bbclient.refreshingTrackList.connect(self.message_overlay.show) def setTrackList(self, track_list, device_info): self.list.clear() self.device_info = device_info self.track_list = track_list for track in track_list: item = QListWidgetItem(track['name']) item.setData(TRACK_ITEM_ROLE, track['id']) self.list.addItem(item) self.message_overlay.hide() def resizeEvent(self, event): self.message_overlay.resize(event.size()) super(HistoryWidget, self).resizeEvent(event) def _onDeleteTracks(self): tracks = self._getSelectedTracks() if not tracks: tracks = self.track_list ids = map(lambda t: t['id'], tracks) names = map(lambda t: t['name'], tracks) msg = 'Are you sure you want to delete the following {} track(s):'.format(len(tracks)) msg += '\n' + '\n'.join(names) res = QMessageBox.question(self, 'Delete tracks?', msg, QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Cancel) print res if res == QMessageBox.Ok: print ids # self.bbclient._refreshTrackList() d = ProgressDialog('Finalizing', "Don't close this window\n(It may stall for a little while on 93%)", self) d.progress.setRange(0, 100) d.resize(250, 80) self.bbclient.finalizingProgress.connect(d.progress.setValue) self.bbclient.tracksDeleted.connect(d.accept) def _onFail(): QMessageBox.warning(self, 'Delete failed') d.accept() self.bbclient.deleteFailed.connect(_onFail) self.bbclient.deleteTracks(ids) d.exec_() def _onUploadStrava(self): tracks = self._getSelectedTracks() if not tracks: tracks = self.track_list strava.upload_to_strava(tracks, self.device_info, self, auth_token=self.config.get('strava_auth_token'), password=self.config.get('strava_password'), username=self.config.get('strava_email')) def _onUploadBrytonSport(self): brytonsport.upload_to_brytonsport(self.bbclient, self, username=self.config.get('bryton_email'), password=self.config.get('bryton_password'), session_id=self.config.get('bryton_session_id')) def _onSaveAsTCX(self): tracks = self._getSelectedTracks() if not tracks: tracks = self.track_list # QMessageBox.information(self, 'No tracks selected', 'You need to select the tracks you want to save.') if not tracks: return if len(tracks) == 1: name = QFileDialog.getSaveFileName(self, 'Save file %s' % tracks[0]['name'], self._trackFilename(tracks[0]['name'], 'tcx'), filter='TCX (*.tcx)') if name: self._saveContent(name, tcx.bryton_gpx_to_tcx(tracks[0]['gpx'], pretty=True, device=self.device_info)) else: dir = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ShowDirsOnly) if not dir: return for t in tracks: name = path.join(str(dir), self._trackFilename(t['name'], 'tcx')) self._saveContent(name, tcx.bryton_gpx_to_tcx(t['gpx'], pretty=True, device=self.device_info)) def _onSaveAsBDX(self): tracks = self._getSelectedTracks() if not tracks: tracks = self.track_list if not tracks: return if len(tracks) == 1: name = QFileDialog.getSaveFileName(self, 'Save file %s' % tracks[0]['name'], self._trackFilename(tracks[0]['name'], 'bdx'), filter='BDX (*.bdx)') if name: self._saveContent(name, tracks[0]['gpx'].toString(pretty=True)) else: dir = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ShowDirsOnly) if not dir: return for t in tracks: name = path.join(str(dir), self._trackFilename(t['name'], 'gpx')) self._saveContent(name, t['gpx'].toString(pretty=True)) def _saveContent(self, filename, content): with open(filename, 'w') as f: f.write(content) def _trackFilename(self, name, ext): return name.replace('/', '').replace(' ', '-').replace(':', '') + '.' + ext def _getSelectedTracks(self): items = self.list.selectedItems() tracks = [] for item in items: index = self.list.row(item) tracks.append(self.track_list[index]) return tracks def _onRowChanged(self, row): track = self.track_list[row] self.currentTrackChanged.emit(track) def _createLayout(self): l = QVBoxLayout() l.addWidget(self.list) h = QHBoxLayout() h.addWidget(self.delete_btn) h.addStretch() h.addWidget(self.save_btn) h.addWidget(self.upload_btn) l.addLayout(h) self.setLayout(l)