use custom dict for db results, and fix fullscreen and downloads

This commit is contained in:
Izalia Mae 2020-09-20 08:28:28 -04:00
parent fc91486a9b
commit 2da6599c44
7 changed files with 141 additions and 132 deletions

View file

@ -46,7 +46,6 @@ Linux (pyqt via pip):
## ToDo
* Use per-webview search bar instead of a global one
* Create a new icon for the toot button
* Create download manager
* Handle cookies
@ -56,6 +55,7 @@ Linux (pyqt via pip):
* Ability to add new custom searches via local or remote json
* Add optional auto-updater with stable/testing channels
* Add ability to 'freeze' tabs
* Add closed tab history
* Rename the damn project
## Bugs

View file

@ -18,75 +18,65 @@ from ..config import var
from ..functions import DotDict
tables = {
'config': OrderedDict([
('id', 'INTEGER PRIMARY KEY'),
('key', 'TEXT UNIQUE'),
('value', 'TEXT')
]),
'bookmarks': OrderedDict([
('id', 'INTEGER PRIMARY KEY'),
('name', 'TEXT'),
('url', 'TEXT UNIQUE'),
('description', 'TEXT'),
('category', 'TEXT'),
('lastupdate', 'DATETIME')
]),
'links': OrderedDict([
('id', 'INTEGER PRIMARY KEY'),
('linkid', 'INTEGER')
]),
'mastodon': OrderedDict([
('id', 'INTEGER PRIMARY KEY'),
('username', 'TEXT'),
('displayname', 'TEXT'),
('domain', 'TEXT'),
('fullname', 'TEXT UNIQUE'),
('apikey', 'TEXT'),
('tootlimit', 'INTEGER'),
('avatar', 'TEXT'),
('lastupdate', 'DATETIME')
]),
'siteoptions': OrderedDict([
('id', 'INTEGER PRIMARY KEY'),
('domain', 'TEXT UNIQUE'),
('microphone', 'BOOLEAN DEFAULT 0'),
('notification', 'BOOLEAN DEFAULT 0'),
('camera', 'BOOLEAN DEFAULT 0'),
('location', 'BOOLEAN DEFAULT 0'),
('fullscreen', 'BOOLEAN DEFAULT 1'),
('javascript', 'BOOLEAN DEFAULT 1'),
('images', 'BOOLEAN DEFAULT 1'),
('adblock', 'BOOLEAN DEFAULT 1'),
('mastodon', 'BOOLEAN DEFAULT 0'),
('allowhttp', 'BOOLEAN DEFAULT 1'),
('capture', 'BOOLEAN DEFAULT 0'),
('cookies', 'BOOLEAN DEFAULT 0'),
('lastupdate', 'DATETIME')
]),
'tabs': OrderedDict([
('id', 'INTEGER PRIMARY KEY'),
('title', 'TEXT'),
('url', 'TEXT'),
('tabid', 'INTEGER')
]),
'search': OrderedDict([
('id', 'INTEGER PRIMARY KEY'),
('name', 'TEXT'),
('keyword', 'TEXT UNIQUE'),
('url', 'TEXT')
]),
#('cookies', {
#'id': 'INTEGER PRIMARY KEY',
#'name': 'TEXT NOT NULL',
#'value': 'TEXT NOT NULL',
#'domain': 'TEXT NOT NULL',
#'path': 'TEXT NOT NULL',
#'expires': 'INTEGER NOT NULL',
#'http_only': 'BOOLEAN NOT NULL',
#'secure': 'BOOLEAN NOT NULL'
#})
}
tables = DotDict({
'config': {
'id': {'type': 'integer', 'options': ['primary key']},
'key': {'type': 'text', 'options': ['unique']},
'value': {'type': 'text'},
},
'bookmarks': {
'id': {'type': 'integer', 'options': ['primary key']},
'name': {'type': 'text'},
'url': {'type': 'text', 'options': ['unique']},
'description': {'type': 'text'},
'category': {'type': 'text'},
'lastupdate': {'type': 'datetime'},
},
'links': {
'id': {'type': 'integer', 'options': ['primary key']},
'linkid': {'type': 'integer'}
},
'mastodon': {
'id': {'type': 'integer', 'options': ['primary key']},
'username': {'type': 'text'},
'displayname': {'type': 'text'},
'domain': {'type': 'text'},
'fullname': {'type': 'text', 'options': 'unique'},
'apikey': {'type': 'text'},
'tootlimit': {'type': 'integer'},
'avatar': {'type': 'text'},
'lastupdate': {'type': 'datetime'},
},
'siteoptions': {
'id': {'type': 'integer', 'options': ['primary key']},
'domain': {'type': 'text', 'options': 'unique'},
'microphone': {'type': 'BOOLEAN', 'default': False},
'notification': {'type': 'BOOLEAN', 'default': False},
'camera': {'type': 'BOOLEAN', 'default': False},
'location': {'type': 'BOOLEAN', 'default': False},
'fullscreen': {'type': 'BOOLEAN', 'default': True},
'javascript': {'type': 'BOOLEAN', 'default': True},
'images': {'type': 'BOOLEAN', 'default': True},
'adblock': {'type': 'BOOLEAN', 'default': True},
'mastodon': {'type': 'BOOLEAN', 'default': False},
'allowhttp': {'type': 'BOOLEAN', 'default': True},
'capture': {'type': 'BOOLEAN', 'default': False},
'cookies': {'type': 'BOOLEAN', 'default': False},
'lastupdate': {'type': 'datetime'}
},
'tabs': {
'id': {'type': 'integer', 'options': ['primary key']},
'title': {'type': 'text'},
'url': {'type': 'text'},
'tabid': {'type': 'integer'}
},
'search': {
'id': {'type': 'integer', 'options': ['primary key']},
'name': {'type': 'text'},
'keyword': {'type': 'text', 'options': ['unique']},
'url': {'type': 'text'}
}
})
SearchEngines = [
@ -281,17 +271,24 @@ class DB():
def CreateTable(self, table):
layout = tables[table]
layout = DotDict(tables.get(table))
if not layout:
logging.error('Table config doesn\'t exist:', table)
return
cmd = f'CREATE TABLE IF NOT EXISTS {table}('
items = []
for k, v in layout.items():
if k != 'foreignkey':
items.append(f'{k} {v}')
options = ' '.join(v.get('options', []))
default = v.get('default')
item = f'{k} {v.type.upper()} {options}'
else:
field, ffield, fcol = layout[k]
items.append(f'FOREIGN KEY({field}) REFERENCES {ffield}({fcol})')
if default:
item += f'DEFAULT {default}'
items.append(item)
cmd += ', '.join(items) + ')'
@ -356,7 +353,7 @@ class DB():
return cookie
class DBResult(dict):
class DBResult(DotDict):
def __init__(self, row, db, table, cursor):
super().__init__()
@ -377,16 +374,24 @@ class DBResult(dict):
def __delattr__(self, name):
if name not in ['db', 'table']:
return self.__getitem__(name)
return self.__delitem__(name)
else:
return super().__delattr__(name)
def __getattr__(self, value, default=None):
val = super().__getattr__(value, default) if default else self[value]
options = [value]
return DotDict(val) if type(val) == dict else val
if default:
options.append(default)
if value in self.keys():
val = super().__getitem__(*options)
return DotDict(val) if isinstance(val, dict) else val
else:
return dict.__getattr__(*options)
# Kept for backwards compatibility. Delete later.
@ -413,25 +418,6 @@ def CreateDatabase():
for engine in SearchEngines:
db.insert('search', engine)
darktheme = {
'name': 'Dark',
'AlternateBase': '#353535',
'Base': '#191919',
'Button': '#353535',
'ButtonText': '#ffffff',
'BrightText': '#ff0000',
'Highlight': '#2a82da',
'HighlightedText': '#000000',
'Link': '#2a82da',
'Text': '#ffffff',
'ToolTipBase': '#000000',
'ToolTipText': '#ffffff',
'Window': '#353535',
'WindowText': '#ffffff'
}
db.insert('themes', darktheme)
perm = True
backupdb = f'{var.database}.backup-{prev_dbversion}'

View file

@ -6,7 +6,7 @@ from ..Lib.IzzyLib.misc import boolean
from ..Lib.IzzyLib import logging
from .connection import db, tables, ParseData
from ..functions import psl
from ..functions import psl, DotDict
from PyQt5.QtGui import QPalette, QColor
@ -50,18 +50,27 @@ def permissions(domain=None, defaults=False):
else:
rows = [db.cache['siteoptions'].fetch(domain)] if domain else cache.values()
for row in rows:
if not row and defaults:
values = [None, None, False, False, False, False, True, True, True, True, False, True, False, False, None]
row = db.resclass['siteoptions'](*values)
if rows == [None]:
rows = None
for k, v in row.asdict().items():
setattr(row, k, boolean(v) if k not in ['id', 'domain', 'lastupdate'] else v)
if not rows and defaults:
row = DotDict()
if domain:
return row
for k, v in tables.siteoptions.items():
default = v.get('default')
row[k] = default if default else None
data.append(row)
return row
else:
for row in rows:
for k, v in row.items():
row[k] = boolean(v) if k not in ['id', 'domain', 'lastupdate'] else v
if domain:
return row
data.append(row)
return data

View file

@ -349,7 +349,7 @@ class NewDownload(QDialog):
logging.verbose('Starting download of', url)
self.SetFilename()
self.download.item.accept()
self.download.item.finished.connect(lambda: profile._download_finished(self.download))
self.download.item.finished.connect(lambda: self.profile._download_finished(self.download))
self.finished = True
self.close()

View file

@ -455,22 +455,19 @@ def ParseSoundcloudInfo(data):
class DotDict(dict):
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __init__(self, value=None, **kwargs):
super().__init__()
self.__setattr__ = dict.__setitem__
self.__delattr__ = dict.__delitem__
self.__getitem__ = self.__getattr__
if value.__class__ == str:
self.FromJson(value)
elif value.__class__ in [dict, DotDict]:
self.update(dict(value))
self.update(value)
elif not value:
pass
else:
elif value:
raise TypeError('The value must be a JSON string, dict, or another DotDict object, not', value.__class__)
if kwargs:
@ -478,17 +475,8 @@ class DotDict(dict):
self.update(kwargs)
def __getattr__(self, value, default=None):
val = self.get(value, default) if default else self[value]
return DotDict(val) if type(val) == dict else val
def ToJson(self, **kwargs):
if not kwargs.get('indent'):
kwargs['indent'] = 4
return json.dumps(self, **kwargs)
return self.__str__(**kwargs)
def FromJson(self, string):
@ -496,6 +484,29 @@ class DotDict(dict):
self.update(data)
def __parse_item(self, data):
return DotDict(data) if type(data) == dict else data
def items(self):
data = []
for k, v in super(DotDict, self).items():
value = self.__parse_item(v)
data.append((k, value))
return data
def __str__(self, **kwargs):
return json.dumps(self, **kwargs)
def __getattr__(self, value, default=None):
val = self.get(value, default) if default else self[value]
return self.__parse_item(val)
def ExceptionHandler(exctype, value, tb):
sys._excepthook(exctype, value, tb)

View file

@ -130,7 +130,7 @@ class WebEngineProfile(QWebEngineProfile):
filename = Path(download.path())
else:
filename = Path(download.downloadDirectory(), download.downloadFileName())
filename = Path(download.item.downloadDirectory(), download.item.downloadFileName())
url = download.item.url().toString()

View file

@ -187,15 +187,18 @@ class WebEngineView(QWebEngineView):
logging.verbose(f'Rejected permission for {host}:', name)
def _fullscreen_request(self, action, request):
host = origin().host()
def _fullscreen_request(self, request):
host = request.origin().host()
site = get.permissions(host, defaults=True)
if site.fullscreen:
logging.verbose('Allowing fullscreen for:', host)
logging.verbose('Allowing fullscreen for', host)
request.accept()
self.Fullscreen(request.toggleOn())
else:
logging.verbose('Disallowing fullscreen for ', host)
def _handle_auth(self, location, authenticator):
url = location.toString()