Qml Calendar And Google Calendar Api In Python Events Integration
Solution 1:
Before modifying any code you must understand the code and understand that it is different with what you want. And in your case there is a difference: The data is not accessed quickly but you have to make a request that is time consuming and can block the GUI.
So before the above it is better to download the events (perhaps save it in a database like sqlite and use the original example) to have it as a cache and thus minimize the amount of downloads.
Then you must separate the logic: Create a class that exports the information to QML, and another class that obtains it.
Since the information will be reloaded every time there is an event, it is better to use a Loader that redraws the GUI every time the cache is updated.
Note: I have used the official example
main.py
import logging
import os
import pickle
import sys
import threading
from PySide2 import QtCore, QtGui, QtQml
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
logging.basicConfig(level=logging.DEBUG)
classCalendarBackend(QtCore.QObject):
eventsChanged = QtCore.Signal(list)
def__init__(self, parent=None):
super().__init__(parent)
self._service = None @propertydefservice(self):
return self._service
defupdateListEvents(self, kw):
threading.Thread(target=self._update_list_events, args=(kw,)).start()
def_update_list_events(self, kw):
self._update_credentials()
events_result = self.service.events().list(**kw).execute()
events = events_result.get("items", [])
qt_events = []
ifnot events:
logging.debug("No upcoming events found.")
for event in events:
start = event["start"].get("dateTime", event["start"].get("date"))
end = event["end"].get("dateTime", event["end"].get("date"))
logging.debug(f"From {start} - To {end}: {event['summary']}")
start_dt = QtCore.QDateTime.fromString(start, QtCore.Qt.ISODate)
end_dt = QtCore.QDateTime.fromString(end, QtCore.Qt.ISODate)
summary = event["summary"]
e = {"start": start_dt, "end": end_dt, "summary": summary}
qt_events.append(e)
self.eventsChanged.emit(qt_events)
def_update_credentials(self):
creds = Noneif os.path.exists("token.pickle"):
withopen("token.pickle", "rb") as token:
creds = pickle.load(token)
ifnot creds ornot creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
"credentials.json", SCOPES
)
creds = flow.run_local_server(port=0)
withopen("token.pickle", "wb") as token:
pickle.dump(creds, token)
self._service = build("calendar", "v3", credentials=creds)
classCalendarProvider(QtCore.QObject):
loaded = QtCore.Signal()
def__init__(self, parent=None):
super().__init__(parent)
self._cache_events = []
self._backend = CalendarBackend()
self._backend.eventsChanged.connect(self._handle_events)
@QtCore.Slot("QVariant")defupdateListEvents(self, parameters):
d = dict()
for k, v in parameters.toVariant().items():
ifisinstance(v, QtCore.QDateTime):
v = v.toTimeSpec(QtCore.Qt.OffsetFromUTC).toString(
QtCore.Qt.ISODateWithMs
)
d[k] = v
self._backend.updateListEvents(d)
@QtCore.Slot(QtCore.QDate, result="QVariantList")defeventsForDate(self, date):
events = []
for event in self._cache_events:
start = event["start"]
if start.date() == date:
events.append(event)
return events
@QtCore.Slot(list)def_handle_events(self, events):
self._cache_events = events
self.loaded.emit()
logging.debug("Loaded")
defmain():
app = QtGui.QGuiApplication(sys.argv)
QtQml.qmlRegisterType(CalendarProvider, "MyCalendar", 1, 0, "CalendarProvider")
engine = QtQml.QQmlApplicationEngine()
filename = os.path.join(CURRENT_DIR, "main.qml")
engine.load(QtCore.QUrl.fromLocalFile(filename))
ifnot engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
main.qml
importQtQuick2.2importQtQuick.Controls1.2importQtQuick.Controls.Private1.0importQtQuick.Controls.Styles1.1importMyCalendar1.0ApplicationWindow {
visible:truewidth:640height:400minimumWidth:400minimumHeight:300color:"#f4f4f4"title:"Calendar Example"SystemPalette {
id:systemPalette
}
CalendarProvider {
id:eventModelonLoaded: {
//reloadloader.sourceComponent=nullloader.sourceComponent=page_component
}
Component.onCompleted: {
eventModel.updateListEvents({
calendarId:"primary",
timeMin:newDate(),
maxResults:10,
singleEvents:true,
orderBy:"startTime",
})
}
}
Loader{
id:loaderanchors.fill:parentsourceComponent:page_component
}
Component{
id:page_componentFlow {
id:rowanchors.fill:parentanchors.margins:20spacing:10layoutDirection:Qt.RightToLeftCalendar {
id:calendarwidth:(parent.width>parent.height?parent.width*0.6 - parent.spacing :parent.width)height:(parent.height>parent.width?parent.height*0.6 - parent.spacing :parent.height)frameVisible:trueweekNumbersVisible:trueselectedDate:newDate()focus:truestyle:CalendarStyle {
dayDelegate:Item {
readonly property color sameMonthDateTextColor:"#444"readonly property color selectedDateColor:Qt.platform.os==="osx"?"#3778d0":systemPalette.highlightreadonly property color selectedDateTextColor:"white"readonly property color differentMonthDateTextColor:"#bbb"readonly property color invalidDatecolor:"#dddddd"Rectangle {
anchors.fill:parentborder.color:"transparent"color:styleData.date!==undefined&&styleData.selected?selectedDateColor :"transparent"anchors.margins:styleData.selected?-1:0
}
Image {
visible:eventModel.eventsForDate(styleData.date).length>0anchors.top:parent.topanchors.left:parent.leftanchors.margins:-1width:12height:widthsource:"images/eventindicator.png"
}
Label {
id:dayDelegateTexttext:styleData.date.getDate()anchors.centerIn:parentcolor: {
varcolor=invalidDatecolor;if(styleData.valid) {
//Dateiswithinthevalidrange.color=styleData.visibleMonth?sameMonthDateTextColor :differentMonthDateTextColor;if(styleData.selected) {
color=selectedDateTextColor;
}
}
color;
}
}
}
}
}
Component {
id:eventListHeaderRow {
id:eventDateRowwidth:parent.widthheight:eventDayLabel.heightspacing:10Label {
id:eventDayLabeltext:calendar.selectedDate.getDate()font.pointSize:35
}
Column {
height:eventDayLabel.heightLabel {
readonly property var options: { weekday:"long" }
text:Qt.locale().standaloneDayName(calendar.selectedDate.getDay(), Locale.LongFormat)font.pointSize:18
}
Label {
text:Qt.locale().standaloneMonthName(calendar.selectedDate.getMonth())+calendar.selectedDate.toLocaleDateString(Qt.locale(), " yyyy")font.pointSize:12
}
}
}
}
Rectangle {
width:(parent.width>parent.height?parent.width*0.4 - parent.spacing :parent.width)height:(parent.height>parent.width?parent.height*0.4 - parent.spacing :parent.height)border.color:Qt.darker(color, 1.2)ListView {
id:eventsListViewspacing:4clip:trueheader:eventListHeaderanchors.fill:parentanchors.margins:10model:eventModel.eventsForDate(calendar.selectedDate)delegate:Rectangle {
width:eventsListView.widthheight:eventItemColumn.heightanchors.horizontalCenter:parent.horizontalCenterImage {
anchors.top:parent.topanchors.topMargin:4width:12height:widthsource:"images/eventindicator.png"
}
Rectangle {
width:parent.widthheight:1color:"#eee"
}
Column {
id:eventItemColumnanchors.left:parent.leftanchors.leftMargin:20anchors.right:parent.rightheight:timeLabel.height+nameLabel.height+8Label {
id:nameLabelwidth:parent.widthwrapMode:Text.Wraptext:modelData["summary"]
}
Label {
id:timeLabelwidth:parent.widthwrapMode:Text.Wraptext:modelData.start.toLocaleTimeString(calendar.locale, Locale.ShortFormat)+"-"+modelData.end.toLocaleTimeString(calendar.locale, Locale.ShortFormat)color:"#aaa"
}
}
}
}
}
}
}
}
The full example is here
Post a Comment for "Qml Calendar And Google Calendar Api In Python Events Integration"