mirror of
https://github.com/Xevion/bulk-reminders.git
synced 2025-12-06 01:14:29 -06:00
156 lines
6.4 KiB
Python
156 lines
6.4 KiB
Python
import logging
|
|
from typing import Any, List, Set
|
|
|
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
|
from PyQt5.QtWidgets import QMainWindow, QMessageBox
|
|
|
|
from bulk_reminders import api
|
|
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
|
|
|
|
logging.basicConfig(format='[%(asctime)s] [%(levelname)s] [%(threadName)s] %(message)s')
|
|
logger = logging.getLogger(__file__)
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
class MainWindow(QMainWindow, Ui_MainWindow):
|
|
def __init__(self, *args, **kwargs):
|
|
# Initial UI setup
|
|
super(MainWindow, self).__init__(*args, **kwargs)
|
|
self.setupUi(self)
|
|
logger.debug('UI Initialized.')
|
|
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: List[IDPair] = []
|
|
self.historyCalendarID: str = ''
|
|
|
|
# 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.apiEvents: List[dict] = []
|
|
|
|
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()
|
|
|
|
def undo(self) -> None:
|
|
"""Get the latest undo stage and delete all events in that stage"""
|
|
logging.info(f'Deleting {len(self.history)} Events from Calendar {self.historyCalendarID}')
|
|
|
|
self.progressBar.show()
|
|
self.progressBar.setMaximum(len(self.history))
|
|
for i, entry in enumerate(self.history):
|
|
logging.debug(f'Deleting Event {entry.eventID}')
|
|
self.calendar.service.events().delete(calendarId=entry.calendarID, eventId=entry.eventID).execute()
|
|
self.progressBar.setValue(i + 1)
|
|
self.progressBar.hide()
|
|
|
|
# Disable the undo button until undo stages are available
|
|
self.history = []
|
|
self.undoButton.setDisabled(len(self.history) == 0)
|
|
self.populate() # Refresh
|
|
|
|
def getForeign(self) -> Set[Any]:
|
|
"""Returns all events currently tracked that are not stored in the undo."""
|
|
foreign = {event.get('id'): event for event in self.apiEvents}
|
|
undoableIDs = set(pair.eventID for pair in self.history)
|
|
return {foreign[eventID] for eventID in undoableIDs.difference(foreign.keys())}
|
|
|
|
def submit(self) -> None:
|
|
self.historyCalendarID = self.currentCalendarID
|
|
self.history = []
|
|
|
|
logger.info(f'Submitting {len(self.readyEvents)} events to API')
|
|
|
|
self.progressBar.show()
|
|
self.progressBar.setMaximum(len(self.readyEvents))
|
|
for i, event in enumerate(self.readyEvents):
|
|
logger.debug(f'Submitting "{event.summary}" scheduled to start on {event.start.isoformat()}....')
|
|
result = self.calendar.service.events().insert(calendarId=self.currentCalendarID, body=event.body).execute()
|
|
self.history.append(IDPair(self.currentCalendarID, result.get('id')))
|
|
self.progressBar.setValue(i + 1)
|
|
|
|
self.undoButton.setDisabled(len(self.history) == 0)
|
|
self.readyEvents.clear()
|
|
self.progressBar.hide()
|
|
|
|
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, foreign = len(self.readyEvents), len(self.history), len(list(self.getForeign()))
|
|
total = ready + undoable + foreign
|
|
self.eventCountLabel.setText(f'{len(self.readyEvents)} ready, {undoable} undoable, {foreign} foreign ({total})')
|
|
|
|
self.eventsView.setRowCount(len(events))
|
|
logger.debug(f'Populating table with {self.eventsView.rowCount()} events.')
|
|
for row, event in enumerate(events):
|
|
logger.debug(f'Event "{event.summary}" starts {event.start} and ends {event.end}')
|
|
event.fill_row(row, self.eventsView)
|
|
|
|
self.submitButton.setDisabled(len(self.readyEvents) < 0)
|
|
|
|
@QtCore.pyqtSlot(int)
|
|
def comboBoxChanged(self, row) -> None:
|
|
"""When the Calendar Selection combobox"""
|
|
self.currentCalendarID = self.comboModel.item(row).data()
|
|
logger.info(f'Switching to Calendar "{self.comboModel.item(row).text()} ({self.currentCalendarID})"')
|
|
self.populate()
|