From 9dc3d0782866a34052ff1d4744be1315a5c01f18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Primo=C5=BE=20Godec?=
Date: Thu, 20 Jun 2019 10:44:22 +0200
Subject: [PATCH] Update widget to save email safely like NYtimes widget
---
orangecontrib/text/widgets/owpubmed.py | 151 +++++++++++++++----------
1 file changed, 91 insertions(+), 60 deletions(-)
diff --git a/orangecontrib/text/widgets/owpubmed.py b/orangecontrib/text/widgets/owpubmed.py
index a518b0c8b..80c5a837a 100644
--- a/orangecontrib/text/widgets/owpubmed.py
+++ b/orangecontrib/text/widgets/owpubmed.py
@@ -1,12 +1,14 @@
import os
+import re
from datetime import date
from AnyQt.QtCore import QDate, Qt
from AnyQt.QtWidgets import (QApplication, QComboBox, QDateEdit, QTextEdit,
- QFrame, QDialog, QCalendarWidget, QVBoxLayout)
-from validate_email import validate_email
+ QFrame, QDialog, QCalendarWidget, QVBoxLayout,
+ QFormLayout)
from Orange.widgets import gui
+from Orange.widgets.credentials import CredentialManager
from Orange.widgets.settings import Setting
from Orange.widgets.widget import OWWidget, Msg
from orangecontrib.text.corpus import Corpus
@@ -20,11 +22,71 @@ def _i(name, icon_path='icons'):
return os.path.join(widget_path, icon_path, name)
+EMAIL_REGEX = re.compile(r"[^@]+@[^@]+\.[^@]+")
+
+
+def validate_email(email):
+ return EMAIL_REGEX.match(email)
+
+
class Output:
CORPUS = 'Corpus'
class OWPubmed(OWWidget):
+ class EmailCredentialsDialog(OWWidget):
+ name = "Pubmed Email"
+ want_main_area = False
+ resizing_enabled = False
+ email_manager = CredentialManager('Email')
+ email_input = ''
+
+ class Error(OWWidget.Error):
+ invalid_credentials = Msg('This email is invalid.')
+
+ def __init__(self, parent):
+ super().__init__()
+ self.parent = parent
+ self.api = None
+
+ form = QFormLayout()
+ form.setContentsMargins(5, 5, 5, 5)
+ self.email_edit = gui.lineEdit(
+ self, self, 'email_input', controlWidth=400)
+ form.addRow('Email:', self.email_edit)
+ self.controlArea.layout().addLayout(form)
+ self.submit_button = gui.button(
+ self.controlArea, self, "OK", self.accept)
+
+ self.load_credentials()
+
+ def setVisible(self, visible):
+ super().setVisible(visible)
+ self.email_edit.setFocus()
+
+ def load_credentials(self):
+ self.email_edit.setText(self.email_manager.key)
+
+ def save_credentials(self):
+ self.email_manager.key = self.email_input
+
+ def check_credentials(self):
+ if validate_email(self.email_input):
+ self.save_credentials()
+ return True
+ else:
+ return False
+
+ def accept(self, silent=False):
+ if not silent:
+ self.Error.invalid_credentials.clear()
+ valid = self.check_credentials()
+ if valid:
+ self.parent.sync_email(self.email_input)
+ super().accept()
+ else:
+ self.Error.invalid_credentials()
+
name = 'Pubmed'
description = 'Fetch data from Pubmed.'
icon = 'icons/Pubmed.svg'
@@ -39,7 +101,6 @@ class OWPubmed(OWWidget):
MIN_DATE = date(1800, 1, 1)
# Settings.
- recent_emails = Setting([])
author = Setting('')
pub_date_from = Setting('')
pub_date_to = Setting('')
@@ -54,11 +115,14 @@ class OWPubmed(OWWidget):
includes_abstract = Setting(True)
includes_url = Setting(True)
+ email = None
+
class Warning(OWWidget.Warning):
no_query = Msg('Please specify the keywords for this query.')
class Error(OWWidget.Error):
api_error = Msg('API error: {}.')
+ email_error = Msg('Email not set. Pleas set it with the email button.')
def __init__(self):
super().__init__()
@@ -66,24 +130,19 @@ def __init__(self):
self.output_corpus = None
self.pubmed_api = None
self.progress = None
- self.email_is_valid = False
self.record_count = 0
self.download_running = False
+ # API key
+ self.email_dlg = self.EmailCredentialsDialog(self)
+ gui.button(self.controlArea, self, 'Email',
+ callback=self.email_dlg.exec_,
+ focusPolicy=Qt.NoFocus)
+ gui.separator(self.controlArea)
+
# To hold all the controls. Makes access easier.
self.pubmed_controls = []
- h_box = gui.hBox(self.controlArea)
- label = gui.label(h_box, self, 'Email:')
- label.setMaximumSize(label.sizeHint())
- # Drop-down for recent emails.
- self.email_combo = QComboBox(h_box)
- self.email_combo.setMinimumWidth(150)
- self.email_combo.setEditable(True)
- self.email_combo.lineEdit().textChanged.connect(self.sync_email)
- h_box.layout().addWidget(self.email_combo)
- self.email_combo.activated[int].connect(self.select_email)
-
# RECORD SEARCH
self.search_tabs = gui.tabWidget(self.controlArea)
# --- Regular search ---
@@ -228,48 +287,29 @@ def __init__(self):
self,
'Number of records retrieved: /')
- # Load the most recent emails.
- self.set_email_list()
-
# Load the most recent queries.
self.set_keyword_list()
- # Check the email and enable controls accordingly.
- if self.recent_emails:
- email = self.recent_emails[0]
- self.email_is_valid = validate_email(email)
-
- self.enable_controls()
-
- def sync_email(self):
- email = self.email_combo.currentText()
- self.email_is_valid = validate_email(email)
- self.enable_controls()
-
- def enable_controls(self):
- # Enable/disable controls accordingly.
- for control in self.pubmed_controls:
- control.setEnabled(self.email_is_valid)
- if self.pubmed_api is None or self.pubmed_api.search_record_count == 0:
- self.retrieve_records_button.setEnabled(False)
- if not self.email_is_valid:
- self.email_combo.setFocus()
+ def sync_email(self, email):
+ self.Error.email_error.clear()
+ self.email = email
def run_search(self):
self.Error.clear()
self.Warning.clear()
+
+ # check if email exists
+ if self.email is None:
+ self.Error.email_error()
+ return
+
self.run_search_button.setEnabled(False)
self.retrieve_records_button.setEnabled(False)
- # Add the email to history.
- email = self.email_combo.currentText()
- if email not in self.recent_emails:
- self.recent_emails.insert(0, email)
-
# Check if the PubMed object is present.
if self.pubmed_api is None:
self.pubmed_api = Pubmed(
- email=email,
+ email=self.email,
progress_callback=self.api_progress_callback,
error_callback=self.api_error_callback,
)
@@ -309,6 +349,13 @@ def run_search(self):
self.enable_controls()
self.update_search_info()
+ def enable_controls(self):
+ # Enable/disable controls accordingly.
+ self.run_search_button.setEnabled(True)
+ enabled = self.pubmed_api is not None and \
+ not self.pubmed_api.search_record_count == 0
+ self.retrieve_records_button.setEnabled(enabled)
+
def retrieve_records(self):
self.Warning.clear()
self.Error.clear()
@@ -318,13 +365,11 @@ def retrieve_records(self):
if self.download_running:
self.download_running = False
- self.run_search_button.setEnabled(True)
self.retrieve_records_button.setText('Retrieve records')
self.pubmed_api.stop_retrieving()
return
self.download_running = True
- self.run_search_button.setEnabled(False)
self.output_corpus = None # Clear the old records.
# Change the button label.
@@ -401,20 +446,6 @@ def update_retrieval_info(self):
self.retrieval_info_label.sizeHint()
)
- def select_email(self, n):
- if n < len(self.recent_emails):
- email = self.recent_emails[n]
- del self.recent_emails[n]
- self.recent_emails.insert(0, email)
-
- if len(self.recent_emails) > 0:
- self.set_email_list()
-
- def set_email_list(self):
- self.email_combo.clear()
- for email in self.recent_emails:
- self.email_combo.addItem(email)
-
def select_keywords(self, n):
if n < len(self.recent_keywords):
keywords = self.recent_keywords[n]