Skip to content

Commit

Permalink
Add test connection button
Browse files Browse the repository at this point in the history
  • Loading branch information
mrvladus committed Oct 12, 2023
1 parent c85860b commit 5960b1e
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 46 deletions.
15 changes: 13 additions & 2 deletions src/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from gi.repository import Adw, Gtk
from .sync import Sync
from .utils import GSettings


Expand All @@ -36,6 +37,7 @@ class PreferencesWindow(Adw.PreferencesWindow):
sync_username: Adw.EntryRow = Gtk.Template.Child()
sync_password: Adw.EntryRow = Gtk.Template.Child()
sync_token: Adw.EntryRow = Gtk.Template.Child()
test_connection_row: Adw.ActionRow = Gtk.Template.Child()

selected_provider = 0

Expand Down Expand Up @@ -65,13 +67,22 @@ def setup_sync(self):
self.sync_url.set_visible(selected != 3 and selected != 0)
self.sync_username.set_visible(selected != 3 and selected != 0)
self.sync_password.set_visible(selected != 3 and selected != 0)
self.window.sync_btn.set_visible(selected > 0)

self.test_connection_row.set_visible(selected > 0)

# --- Template handlers --- #

@Gtk.Template.Callback()
def on_sync_provider_selected(self, *_) -> None:
self.setup_sync()

# --- Template handlers --- #
@Gtk.Template.Callback()
def on_test_connection_btn_clicked(self, btn):
res: bool = Sync.test_connection()
msg = _("Connected") if res else _("Can't connect") # pyright:ignore
toast: Adw.Toast = Adw.Toast(title=msg, timeout=2)
self.add_toast(toast)
self.window.sync_btn.set_visible(res)

@Gtk.Template.Callback()
def on_theme_change(self, btn: Gtk.Button) -> None:
Expand Down
14 changes: 14 additions & 0 deletions src/res/ui/preferences.ui
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@
</object>
</child>

<!-- Test connection -->
<child>
<object class="AdwActionRow" id="test_connection_row">
<property name="title" translatable="yes">Test Connection</property>
<child>
<object class="GtkButton" id="test_connection_btn">
<property name="label" translatable="yes">Test</property>
<property name="valign">center</property>
<signal name="clicked" handler="on_test_connection_btn_clicked" />
</object>
</child>
</object>
</child>

</object>
</child>

Expand Down
1 change: 1 addition & 0 deletions src/res/ui/window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@
<child type="end">
<object class="GtkButton" id="sync_btn">
<property name="icon-name">emblem-synchronizing-symbolic</property>
<property name="visible">false</property>
<property name="tooltip-text" translatable="yes">Sync/Fetch Tasks</property>
<signal name="clicked" handler="on_sync_btn_clicked" />
<accessibility>
Expand Down
102 changes: 58 additions & 44 deletions src/sync.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from gi.repository import Adw, GLib
from caldav import Calendar, DAVClient
from caldav import Calendar, DAVClient, Principal
from .utils import GSettings, Log, TaskUtils, UserData, threaded


Expand All @@ -8,7 +8,7 @@ class Sync:
window: Adw.ApplicationWindow = None

@classmethod
def init(self, window: Adw.ApplicationWindow = None) -> None:
def init(self, window: Adw.ApplicationWindow = None, testing: bool = False) -> None:
Log.debug("Initialize sync provider")
if window:
self.window = window
Expand All @@ -17,8 +17,7 @@ def init(self, window: Adw.ApplicationWindow = None) -> None:
Log.info("Sync disabled")
self.window.sync_btn.set_visible(False)
case 1:
self.provider = SyncProviderCalDAV("Nextcloud", self.window)
self.window.sync_btn.set_visible(True)
self.provider = SyncProviderCalDAV("Nextcloud", self.window, testing)

@classmethod
@threaded
Expand All @@ -33,76 +32,75 @@ def sync(self, fetch: bool = False) -> None:
if self.provider and self.provider.can_sync:
self.provider.sync(fetch)

@classmethod
def test_connection(self) -> bool:
self.init(testing=True)
return self.provider.can_sync


class SyncProviderCalDAV:
can_sync: bool = False
calendar: Calendar = None
window = None

def __init__(self, name: str, window: Adw.ApplicationWindow) -> None:
def __init__(self, name: str, window: Adw.ApplicationWindow, testing: bool) -> None:
Log.info(f"Initialize {name} sync provider")

self.name = name
self.window = window
self.testing = testing # Only for connection test

if not self._check_credentials():
return

self._check_url()
return self._connect()

def _check_credentials(self) -> bool:
self.url = GSettings.get("sync-url")
self.username = GSettings.get("sync-username")
self.password = GSettings.get("sync-password")

if self.url == "" or self.username == "" or self.password == "":
Log.error(f"Not all {self.name} credentials provided")
self.window.add_toast(
_( # pyright:ignore
"Not all sync credentials provided. Please check settings."
if not self.testing:
self.window.add_toast(
_( # pyright:ignore
"Not all sync credentials provided. Please check settings."
)
)
)
self.window.sync_btn.set_visible(False)
return
return False

self._set_url()
self.window.sync_btn.set_visible(True)
return True

def _check_url(self) -> None:
if not self.url.startswith("http"):
self.url = "http://" + self.url
GSettings.set("sync-url", "s", self.url)
if self.name == "Nextcloud":
self.url = f"{self.url}/remote.php/dav/"

def _connect(self) -> bool:
with DAVClient(
url=self.url, username=self.username, password=self.password
) as client:
try:
supports_caldav = client.check_cdav_support()
if not supports_caldav:
Log.error(f"Server doesn't support CalDAV. Maybe wrong adress?")
self.window.add_toast(
_( # pyright:ignore
"Server doesn't support CalDAV. Maybe wrong adress?"
)
)
return

principal = client.principal()
Log.info(f"Connected to {self.name} CalDAV server at '{self.url}'")
self.can_sync = True
self._setup_calendar(principal)
self.window.sync_btn.set_visible(True)
except:
Log.error(f"Can't connect to {self.name} CalDAV server at '{self.url}'")
self.window.add_toast(_("Sync is Disabled")) # pyright:ignore
if not self.testing:
self.window.add_toast(
_("Can't connect to CalDAV server at:") # pyright:ignore
+ " "
+ self.url
)
self.window.sync_btn.set_visible(False)
return
# Get calendars
calendars = principal.calendars()
# Check if Errands calendar exists
errands_cal_exists: bool = False
for cal in calendars:
if cal.name == "Errands":
self.calendar = cal
errands_cal_exists = True
# Create one if not
if not errands_cal_exists:
Log.debug(f"Create new calendar 'Errands' on {self.name}")
self.calendar = principal.make_calendar(
"Errands", supported_calendar_component_set=["VTODO"]
)

def _set_url(self):
if not self.url.startswith("http"):
self.url = "http://" + self.url
GSettings.set("sync-url", "s", self.url)
if self.name == "Nextcloud":
self.url = f"{self.url}/remote.php/dav/"

def _get_tasks(self) -> list[dict]:
"""
Expand Down Expand Up @@ -182,6 +180,22 @@ def _fetch(self):

UserData.set(data)

def _setup_calendar(self, principal: Principal) -> None:
# Get calendars
calendars: list[Calendar] = principal.calendars()
# Check if Errands calendar exists
errands_cal_exists: bool = False
for cal in calendars:
if cal.name == "Errands":
self.calendar = cal
errands_cal_exists = True
# Create one if not
if not errands_cal_exists:
Log.debug(f"Create new calendar 'Errands' on {self.name}")
self.calendar = principal.make_calendar(
"Errands", supported_calendar_component_set=["VTODO"]
)

def sync(self, fetch: bool) -> None:
"""
Sync local tasks with provider
Expand Down

0 comments on commit 5960b1e

Please sign in to comment.