Files
bulk-reminders/bulk_reminders/gui.py

130 lines
5.3 KiB
Python

from typing import Iterator, List
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QMessageBox
from bulk_reminders import api, undo
from bulk_reminders.api import Event
from bulk_reminders.gui_base import Ui_MainWindow
from bulk_reminders.load import LoadDialog
from bulk_reminders.oauth import OAuthDialog
from bulk_reminders.undo import IDPair, Stage
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
# Initial UI setup
super(MainWindow, self).__init__(*args, **kwargs)
self.setupUi(self)
self.show()
self.calendar = api.Calendar()
self.currentCalendarID = 'primary'
# Authenticate user into Google API Engine
self.authenticated = self.calendar.authenticate_via_token()
if not self.authenticated:
temp_dialog = OAuthDialog(callback=self.calendar.authenticate_via_oauth)
temp_dialog.show()
self.calendar.setupService()
# Get Calendars, Setup Calendar Selection Combobox
calendars = self.calendar.getCalendarsSimplified()
self.comboModel = QtGui.QStandardItemModel()
for id, summary in calendars:
item = QtGui.QStandardItem(summary)
item.setData(id)
self.comboModel.appendRow(item)
self.calendarCombobox.setModel(self.comboModel)
self.calendarCombobox.currentIndexChanged[int].connect(self.comboBoxChanged)
# Make sure the current calendar ID matches up
self.currentCalendarID = self.comboModel.item(self.calendarCombobox.currentIndex()).data()
# Setup Column View headers
self.eventsView.setColumnCount(4)
self.eventsView.setHorizontalHeaderLabels(['Summary', 'Status', 'Start', 'End'])
header = self.eventsView.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
self.eventsView.verticalHeader().hide()
self.undoButton.clicked.connect(self.undo)
self.submitButton.clicked.connect(self.submit)
self.history = undo.HistoryManager('history.json')
# Disable the undo button until undo stages are available
if len(self.history) == 0:
self.undoButton.setDisabled(True)
self.loadEventsButton.clicked.connect(self.load_events)
self.cachedLoadText = ''
self.readyEvents: List[Event] = []
self.populate()
def load_events(self) -> None:
"""Open the event loading dialog"""
dial = LoadDialog()
dial.plainTextEdit.setPlainText(self.cachedLoadText)
result = dial.exec()
if result == QMessageBox.Accepted:
self.cachedLoadText = dial.plainTextEdit.toPlainText()
self.readyEvents = dial.parsed
self.populate()
elif result == QMessageBox.Cancel:
pass
def undo(self) -> None:
# Get the latest undo stage and delete all events in that stage
latest = self.history.pop()
for entry in latest.events:
self.calendar.service.events().delete(calendarId=entry.calendarID, eventId=entry.eventID).execute()
# Disable the undo button until undo stages are available
self.undoButton.setDisabled(len(self.history) == 0)
self.populate() # Refresh
def getForeign(self) -> Iterator[IDPair]:
"""Returns all events currently tracked that are not stored in the undo."""
undoableIDs = set(self.history.all_pairs())
for apiEvent in self.apiEvents:
pair = IDPair(calendarID=self.currentCalendarID, eventID=apiEvent['id'])
if pair not in undoableIDs:
yield pair
def submit(self) -> None:
newStage = Stage(index=self.history.nextIndex(), commonCalendar=self.currentCalendarID)
while self.readyEvents:
event: Event = self.readyEvents.pop(0)
result = self.calendar.service.events().insert(calendarId=self.currentCalendarID, body=event.body).execute()
newStage.events.append(IDPair(self.currentCalendarID, result.get('id')))
self.history.addStage(newStage)
self.populate()
def populate(self) -> None:
"""Re-populate the table with all of the events"""
self.apiEvents = self.calendar.getEvents(self.currentCalendarID)
events = list(self.readyEvents)
events.extend([Event.from_api(event, self.history) for event in self.apiEvents])
ready, undoable, stage, foreign = len(self.readyEvents), self.history.getTotal(), len(self.history), len(list(self.getForeign()))
total = ready + undoable + foreign
self.eventCountLabel.setText(f'{len(self.readyEvents)} ready, {undoable} undoable in {stage} stages, {foreign} foreign ({total})')
self.eventsView.setRowCount(len(events))
for row, event in enumerate(events):
event.fill_row(row, self.eventsView)
@QtCore.pyqtSlot(int)
def comboBoxChanged(self, row) -> None:
"""When the Calendar Selection combobox"""
self.currentCalendarID = self.comboModel.item(row).data()
self.populate()