a lot
This commit is contained in:
parent
66561a94d9
commit
6ac080f480
14
README.md
14
README.md
|
@ -4,11 +4,13 @@ Web browser written in Python and Qt with PyQt5
|
|||
|
||||
## Features
|
||||
|
||||
*
|
||||
* Quick access to various page functions in the status bar
|
||||
* Login to a Mastodon account
|
||||
* Quick access to domain permissions in the status bar
|
||||
* Create new Mastodon posts without going to the webui
|
||||
* Interact with Mastodon posts by right-clicking the post's url
|
||||
* Control the browser via cli from a terminal
|
||||
* Ability to add user scripts (basic support atm)
|
||||
* Custom searches via keyword
|
||||
* Remote web dev tools (localhost only atm)
|
||||
|
||||
note: I may add full pleroma support in the future
|
||||
|
||||
|
@ -31,7 +33,7 @@ Make sure you add Python to PATH
|
|||
### Python dependencies
|
||||
|
||||
Windows:
|
||||
|
||||
|
||||
pip3 install -r requirements.txt -r requirements-win.txt
|
||||
|
||||
Linux:
|
||||
|
@ -48,6 +50,7 @@ Linux (pyqt via pip):
|
|||
* Handle cookies
|
||||
* Add folder structure for bookmarks
|
||||
* Create history tab
|
||||
* Add proxy support
|
||||
* Ability to add new custom searches via local or remote json
|
||||
* Add optional auto-updater with stable/testing channels
|
||||
* Add ability to 'freeze' tabs
|
||||
|
@ -55,9 +58,9 @@ Linux (pyqt via pip):
|
|||
|
||||
## Bugs
|
||||
|
||||
* Resetting a page search sometimes scrolls the page to the top or an element on the page
|
||||
* Web notifications use the wrong icon sometimes
|
||||
* Switching between PyQt versions resets cookies
|
||||
* Stop and reload buttons occasionally don't get set properly after finished loading
|
||||
* The nitter redirect only works when loading a url from the navbar
|
||||
* Web inspector is kinda broken
|
||||
* The webview is really blurry and glitchy in virtualbox with the VboxSVGA controller with 3d accel enabled
|
||||
|
@ -68,3 +71,4 @@ Linux (pyqt via pip):
|
|||
* No web notification support in QWebEngine
|
||||
* Download urls with query parameters will probably produce junk names atm because QWebEngineDownloadItem.suggestedFileName() doesn't exist
|
||||
* Can't login to twitch.tv and channels sometimes don't load
|
||||
* Can't browse github code trees. Use right click > Open Link in New Tab to work around the issue for now
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
__application__ = 'QtWeb'
|
||||
__version_info__ = (0,1,6,9)
|
||||
__version_info__ = (0,1,7)
|
||||
__version__ = '.'.join(str(v) for v in __version_info__)
|
||||
__author__ = 'Zoey Mae'
|
||||
|
||||
dbversion = 202008150250
|
||||
prev_dbversion = 202008052224
|
||||
dbversion = 202008200718
|
||||
prev_dbversion = 202008150250
|
||||
|
||||
|
||||
import sys
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
import sys
|
||||
|
||||
from collections import namedtuple
|
||||
from os.path import abspath, dirname, join, isdir, expanduser
|
||||
from os.path import abspath, dirname, join, isdir
|
||||
from os import environ, makedirs, walk
|
||||
from random import randint
|
||||
|
||||
from . import __version__, __application__, isWindows
|
||||
from .arguments import profile
|
||||
|
||||
from .Lib.IzzyLib import logging
|
||||
from .Lib.IzzyLib.misc import randomgen
|
||||
|
||||
import PyQt5
|
||||
from PyQt5.QtCore import QStandardPaths
|
||||
from PyQt5.QtWebEngineWidgets import QWebEngineProfile
|
||||
|
||||
|
@ -41,12 +38,21 @@ variables = {
|
|||
'lock': join(datapath, profile, 'lock.pid'),
|
||||
'home': home,
|
||||
'temp': join(temp, 'qtweb'),
|
||||
'local': 'web:'
|
||||
'local': 'qtweb'
|
||||
}
|
||||
|
||||
|
||||
default_vars = {
|
||||
'homepage': 'https://ddg.gg',
|
||||
'nitter': 'https://nitter.net',
|
||||
'mhost': '127.0.0.1',
|
||||
'mport': 8008
|
||||
}
|
||||
|
||||
|
||||
# Set various variables
|
||||
var = namedtuple('Variables', variables.keys())(*variables.values())
|
||||
default = namedtuple('Default', default_vars.keys())(*default_vars.values())
|
||||
|
||||
## create necessary data dirs
|
||||
if not isdir(var.profilepath):
|
||||
|
@ -55,5 +61,7 @@ if not isdir(var.profilepath):
|
|||
if not isdir(var.temp):
|
||||
makedirs(var.temp, exist_ok=True)
|
||||
|
||||
if not isdir(join(var.datapath, 'UserScripts')):
|
||||
makedirs(join(var.datapath, 'UserScripts'), exist_ok=True)
|
||||
|
||||
environ['QTWEBENGINE_DICTIONARIES_PATH'] = join(var.resources, 'dictionaries')
|
||||
#environ['QTWEBENGINE_REMOTE_DEBUGGING'] = '127.0.0.1:8018'
|
||||
|
|
|
@ -16,13 +16,12 @@ from DBUtils.PooledDB import PooledDB
|
|||
|
||||
from .. import dbversion, prev_dbversion
|
||||
from ..config import var
|
||||
from ..functions import DateTime
|
||||
|
||||
|
||||
tables = {
|
||||
'config': OrderedDict([
|
||||
('id', 'INTEGER PRIMARY KEY'),
|
||||
('key', 'TEXT'),
|
||||
('key', 'TEXT UNIQUE'),
|
||||
('value', 'TEXT')
|
||||
]),
|
||||
'bookmarks': OrderedDict([
|
||||
|
@ -42,7 +41,7 @@ tables = {
|
|||
('username', 'TEXT'),
|
||||
('displayname', 'TEXT'),
|
||||
('domain', 'TEXT'),
|
||||
('fullname', 'TEXT'),
|
||||
('fullname', 'TEXT UNIQUE'),
|
||||
('apikey', 'TEXT'),
|
||||
('tootlimit', 'INTEGER'),
|
||||
('avatar', 'TEXT'),
|
||||
|
@ -50,7 +49,7 @@ tables = {
|
|||
]),
|
||||
'siteoptions': OrderedDict([
|
||||
('id', 'INTEGER PRIMARY KEY'),
|
||||
('domain', 'TEXT'),
|
||||
('domain', 'TEXT UNIQUE'),
|
||||
('microphone', 'BOOLEAN DEFAULT 0'),
|
||||
('notification', 'BOOLEAN DEFAULT 0'),
|
||||
('camera', 'BOOLEAN DEFAULT 0'),
|
||||
|
@ -135,6 +134,7 @@ def ParseData(table, row):
|
|||
class DB():
|
||||
def __init__(self, dbfile=var.database):
|
||||
self.db = PooledDB(sqlite3, database=dbfile, maxconnections=50, mincached=5, maxusage=1)
|
||||
self.window = None
|
||||
self.cache = {}
|
||||
self.resclass = {}
|
||||
|
||||
|
@ -221,7 +221,6 @@ class DB():
|
|||
def fetch(self, table, rowid=None, single=True, sort=None, **kwargs):
|
||||
db = self
|
||||
table = table if tables.get(table) else table.replace('_migrate', '')
|
||||
tablekeys = self._table_keys(table)
|
||||
querysort = f'ORDER BY {sort}'
|
||||
Result = self.resclass.get(table, None)
|
||||
|
||||
|
@ -385,10 +384,30 @@ def CreateDatabase():
|
|||
db.CreateTable(name)
|
||||
|
||||
db.insert('config', {'key': 'version', 'value': dbversion})
|
||||
db.insert('config', {'key': 'search', 'value': 'ddg'})
|
||||
|
||||
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}'
|
||||
|
|
|
@ -6,7 +6,9 @@ from ..Lib.IzzyLib.misc import boolean
|
|||
from ..Lib.IzzyLib import logging
|
||||
|
||||
from .connection import db, tables, ParseData
|
||||
from ..functions import psl, DateTime
|
||||
from ..functions import psl
|
||||
|
||||
from PyQt5.QtGui import QPalette, QColor
|
||||
|
||||
|
||||
def config(key=None, default=None):
|
||||
|
@ -101,3 +103,24 @@ def search(keyword):
|
|||
cache.store(keyword, row)
|
||||
|
||||
return row
|
||||
|
||||
|
||||
def theme(name=None):
|
||||
if name:
|
||||
row = db.fetch('themes', name=name)
|
||||
|
||||
if not row:
|
||||
logging.error('Cannot find color theme:', name)
|
||||
return
|
||||
|
||||
row.palette = db.window.themes.ColorToPalette(row.asdict())
|
||||
|
||||
return row
|
||||
|
||||
else:
|
||||
rows = db.fetch('themes', single=False)
|
||||
|
||||
for row in rows:
|
||||
row.palette = db.window.themes.ColorToPalette(row.asdict())
|
||||
|
||||
return rows
|
||||
|
|
|
@ -22,7 +22,6 @@ from PyQt5.QtCore import QDateTime
|
|||
def run(version):
|
||||
global db
|
||||
backupdb = var.database + f'.backup-{version}'
|
||||
version_row = db.fetch('config', key='version')
|
||||
version = int(version)
|
||||
|
||||
if not isfile(backupdb):
|
||||
|
@ -89,4 +88,5 @@ def run(version):
|
|||
|
||||
db.UpVersion(202008150250)
|
||||
|
||||
|
||||
logging.info(f'Updated database to version {dbversion} :3')
|
||||
|
|
|
@ -106,8 +106,18 @@ def tab(tabid, url, title):
|
|||
tabrow = db.fetch('tabs', url=url)
|
||||
|
||||
if not tabrow:
|
||||
result = db.insert('tabs', {'title': title, 'url': url, 'tabid': tabid})
|
||||
op = 'insert'
|
||||
db.insert('tabs', {'title': title, 'url': url, 'tabid': tabid})
|
||||
|
||||
else:
|
||||
result = db.update('tabs', tabrow.id, {'title': title, 'url': url, 'tabid': tabid})
|
||||
op = 'update'
|
||||
tabrow.Update({'title': title, 'url': url, 'tabid': tabid})
|
||||
|
||||
|
||||
def theme(name, palette):
|
||||
row = get.theme(name)
|
||||
data = db.window.themes.PaletteToColor(palette)
|
||||
|
||||
if row:
|
||||
row.Update(data)
|
||||
|
||||
else:
|
||||
db.insert('themes', data)
|
||||
|
|
|
@ -15,10 +15,13 @@ from PyQt5.QtWidgets import *
|
|||
from PyQt5 import uic
|
||||
|
||||
|
||||
class EditBookmark(object):
|
||||
def __init__(self, title=None, url=None, row=None):
|
||||
self.ui = uic.loadUi(join(var.resources, 'editbookmark.ui'))
|
||||
self.ui.setWindowTitle('Add/Edit Bookmark')
|
||||
class EditBookmark(QDialog):
|
||||
def __init__(self, parent, title=None, url=None, row=None):
|
||||
super().__init__(parent)
|
||||
self.ui = uic.loadUi(join(var.resources, 'dialog-bookmark.ui'))
|
||||
self.parent = parent
|
||||
self.setLayout(self.ui.layout())
|
||||
self.setWindowTitle('Add/Edit Bookmark')
|
||||
|
||||
self.row = row if row else db.fetch('bookmarks', url=url)
|
||||
|
||||
|
@ -57,19 +60,23 @@ class EditBookmark(object):
|
|||
if action:
|
||||
action['cmd'](*action.get('args', []), **action.get('kwargs', {}))
|
||||
|
||||
self.ui.deleteLater()
|
||||
del self
|
||||
self.close()
|
||||
self.deleteLater()
|
||||
del self.parent.open_dialogs['bookmarkedit']
|
||||
|
||||
|
||||
class SiteSettings(object):
|
||||
def __init__(self, host):
|
||||
self.ui = uic.loadUi(join(var.resources, 'sitesettings.ui'))
|
||||
class SiteSettings(QDialog):
|
||||
def __init__(self, parent, host):
|
||||
super().__init__(parent)
|
||||
self.ui = uic.loadUi(join(var.resources, 'dialog-sitesettings.ui'))
|
||||
self.setLayout(self.ui.layout())
|
||||
self.parent = parent
|
||||
self.domain = host
|
||||
self.ui.setWindowTitle(self.domain.title())
|
||||
self.setWindowTitle(self.domain.title())
|
||||
|
||||
self.row = get.permissions(self.domain, defaults=True)
|
||||
|
||||
if not self.row:
|
||||
if not self.row.domain:
|
||||
self.ui.reset.setEnabled(False)
|
||||
|
||||
else:
|
||||
|
@ -82,6 +89,7 @@ class SiteSettings(object):
|
|||
self.ui.location.setChecked(self.row.location)
|
||||
self.ui.camera.setChecked(self.row.camera)
|
||||
self.ui.allowhttp.setChecked(self.row.allowhttp)
|
||||
self.ui.mastodon.setChecked(self.row.mastodon)
|
||||
|
||||
self.ui.save.clicked.connect(lambda : self._button_click('save'))
|
||||
self.ui.reset.clicked.connect(lambda : self._button_click('reset'))
|
||||
|
@ -100,7 +108,8 @@ class SiteSettings(object):
|
|||
'location': self.ui.location.isChecked(),
|
||||
'fullscreen': self.ui.fullscreen.isChecked(),
|
||||
'adblock': self.ui.adblock.isChecked(),
|
||||
'allowhttp': self.ui.allowhttp.isChecked()
|
||||
'allowhttp': self.ui.allowhttp.isChecked(),
|
||||
'mastodon': self.ui.mastodon.isChecked()
|
||||
}
|
||||
|
||||
actions = {
|
||||
|
@ -113,17 +122,20 @@ class SiteSettings(object):
|
|||
if action:
|
||||
action['cmd'](*action.get('args', []), **action.get('kwargs', {}))
|
||||
|
||||
self.close()
|
||||
self.ui.deleteLater()
|
||||
del self
|
||||
del self.parent.open_dialogs['siteedit']
|
||||
|
||||
|
||||
class Toot():
|
||||
def __init__(self, window, mastodon, data=None, reply=None):
|
||||
self.window = window
|
||||
self.mastodon = mastodon
|
||||
class Toot(QDialog):
|
||||
def __init__(self, parent, data=None, reply=None):
|
||||
super().__init__(parent)
|
||||
self.ui = uic.loadUi(join(var.resources, 'dialog-toot.ui'))
|
||||
self.setLayout(self.ui.layout())
|
||||
self.setWindowTitle('New Toot')
|
||||
|
||||
self.ui = uic.loadUi(join(var.resources, 'toot.ui'))
|
||||
self.ui.setWindowTitle('New Toot')
|
||||
self.parent = parent
|
||||
self.mastodon = parent.mastodon
|
||||
self.accounts = {}
|
||||
self.reply = reply
|
||||
self.post = None
|
||||
|
@ -196,7 +208,7 @@ class Toot():
|
|||
def _get_post_data(self):
|
||||
currentacct = self.ui.account.currentData()
|
||||
|
||||
data = self.window.mastodon.GetPostData(self.reply, currentacct)
|
||||
data = self.mastodon.GetPostData(self.reply, currentacct)
|
||||
|
||||
if not data:
|
||||
return
|
||||
|
@ -253,19 +265,16 @@ class Toot():
|
|||
if action:
|
||||
action['cmd'](*action.get('args', []), **action.get('kwargs', {}))
|
||||
|
||||
self.close()
|
||||
self.ui.deleteLater()
|
||||
del self
|
||||
|
||||
|
||||
def show(self):
|
||||
self.ui.exec_()
|
||||
del self.parent.open_dialogs['toot']
|
||||
|
||||
|
||||
class NewDownload(QDialog):
|
||||
def __init__(self, download, profile):
|
||||
super().__init__()
|
||||
|
||||
self.ui = uic.loadUi(join(var.resources, 'newdownload.ui'))
|
||||
self.ui = uic.loadUi(join(var.resources, 'dialog-download.ui'))
|
||||
self.setWindowTitle('Download File: ')
|
||||
self.setModal(True)
|
||||
self.setFixedHeight(200)
|
||||
|
@ -354,3 +363,35 @@ class NewDownload(QDialog):
|
|||
else:
|
||||
self.download.setDownloadDirectory(str(filename.parent))
|
||||
self.download.setDownloadFileName(str(filename.name))
|
||||
|
||||
|
||||
class HttpAuth(QDialog):
|
||||
def __init__(self, url, authenticator, parent):
|
||||
super().__init__(parent.window)
|
||||
|
||||
self.ui = uic.loadUi(join(var.resources, 'dialog-authentication.ui'))
|
||||
self.ui.savepass.setEnabled(False)
|
||||
self.setLayout(self.ui.layout())
|
||||
|
||||
self.webview = parent
|
||||
self.url = url
|
||||
self.auth = authenticator
|
||||
self.username = None
|
||||
self.password = None
|
||||
self.result = False
|
||||
|
||||
text = self.ui.realm.text().format(host=url.host(), msg=self.auth.realm())
|
||||
self.ui.realm.setText(text)
|
||||
|
||||
self.ui.login.clicked.connect(lambda : self._handle_close_button('login'))
|
||||
self.ui.cancel.clicked.connect(self._handle_close_button)
|
||||
|
||||
|
||||
def _handle_close_button(self, button=None):
|
||||
if button == 'login':
|
||||
self.auth.setUser(self.ui.username.text())
|
||||
self.auth.setPassword(self.ui.password.text())
|
||||
self.result = True
|
||||
|
||||
self.close()
|
||||
self.deleteLater()
|
||||
|
|
106
qtweb/filter.py
106
qtweb/filter.py
|
@ -1,106 +0,0 @@
|
|||
import threading, sys, os
|
||||
|
||||
from datetime import datetime
|
||||
from os.path import join
|
||||
|
||||
from .Lib.IzzyLib import logging
|
||||
from publicsuffixlist import PublicSuffixList
|
||||
from publicsuffixlist.update import updatePSL
|
||||
|
||||
from . import pyqtver, debstable
|
||||
from .database import db, get, put
|
||||
from .functions import GetSoftware, httpclient
|
||||
|
||||
from PyQt5.QtCore import QUrl
|
||||
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
|
||||
|
||||
|
||||
#if hasattr(sys, '_MEIPASS'):
|
||||
#os.makedirs(join(sys._MEIPASS, 'publicsuffixlist'), exist_ok=True)
|
||||
#with open(join(sys._MEIPASS, 'publicsuffixlist', 'public_suffix_list.dat'), 'w') as fd:
|
||||
#resp = httpclient.request('GET', 'https://publicsuffix.org/list/public_suffix_list.dat')
|
||||
#fd.write(resp.data.decode())
|
||||
|
||||
|
||||
psl = PublicSuffixList()
|
||||
extract = psl.privatesuffix
|
||||
|
||||
|
||||
## blocked domains and urls (will be optional in the future)
|
||||
blockedDomain = [
|
||||
'doubleclick.net',
|
||||
'rubiconproject.com',
|
||||
'outbrain.com',
|
||||
'googletagservices.com',
|
||||
'amazon-adsystem.com',
|
||||
'optimizely.com',
|
||||
'adswizz.com'
|
||||
]
|
||||
|
||||
blockedURL = {
|
||||
'youtube.com': [
|
||||
'/api/stats/ads',
|
||||
'/pagead/adview',
|
||||
'/pagead/lvz'
|
||||
'/get_midroll/info'
|
||||
],
|
||||
'soundcloud.com': [
|
||||
'/audio-ads'
|
||||
],
|
||||
'facebook.com': [
|
||||
'/tr']
|
||||
}
|
||||
|
||||
|
||||
class WebFilter(QWebEngineUrlRequestInterceptor):
|
||||
def __init__(self, window):
|
||||
super().__init__()
|
||||
self.window = window
|
||||
self.threads = {}
|
||||
|
||||
def interceptRequest(self, info):
|
||||
requrl = info.requestUrl()
|
||||
reqdomain = requrl.host()
|
||||
reqtopdomain = extract(reqdomain)
|
||||
reqpath = requrl.path()
|
||||
|
||||
pageurl = info.firstPartyUrl()
|
||||
pagedomain = pageurl.host()
|
||||
pagetopdomain = extract(pagedomain)
|
||||
pagepath = pageurl.path()
|
||||
|
||||
pagerow = get.permissions(pagedomain, defaults=True)
|
||||
|
||||
## Prevent secure pages from loading insecure content
|
||||
if not pagerow.allowhttp and requrl.scheme() == 'http' and pageurl.scheme() == 'https':
|
||||
logging.verbose('Blocked insecure content:', requrl.toString().split('?', 1)[0])
|
||||
info.block(True)
|
||||
return
|
||||
|
||||
## Block requests if they're in the block list
|
||||
if self.window.adblock and pagerow.adblock and (reqpath in blockedURL.get(reqdomain, []) or reqdomain in blockedDomain or reqtopdomain in blockedDomain):
|
||||
logging.verbose('Blocked content:', requrl.toString().split('?', 1)[0])
|
||||
info.block(True)
|
||||
return
|
||||
|
||||
## Set custom headers
|
||||
info.setHttpHeader("trans-rights".encode(), "are human rights".encode())
|
||||
|
||||
## Check if domain is a mastodon instance
|
||||
if not pagerow.domain and not pagerow.mastodon and not any(map(requrl.toString().startswith, ['about:', 'chrome://'])):
|
||||
if not pagedomain:
|
||||
return
|
||||
|
||||
if self.threads.get(pagedomain):
|
||||
return
|
||||
|
||||
self.threads[pagedomain] = threading.Thread(target=GetSoftware, args=[pagedomain])
|
||||
self.threads[pagedomain].start()
|
||||
|
||||
## Delete the thread object once it's finished
|
||||
elif self.threads.get(pagedomain):
|
||||
del self.threads[pagedomain]
|
||||
|
||||
## Google is a fuck and is very picky about what browsers are supported
|
||||
#if 'google.com' in [pagetopdomain, reqtopdomain]:
|
||||
#info.setHttpHeader('user-agent'.encode(), 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0'.encode())
|
|
@ -47,14 +47,19 @@ class Notifications(object):
|
|||
self.New('Error', message)
|
||||
|
||||
|
||||
def Icon(name):
|
||||
def Icon(name, size=None):
|
||||
filename = join(var.iconpath, name + '.svg')
|
||||
|
||||
if not isfile(filename):
|
||||
logging.error('Invalid icon name:', name)
|
||||
return QIcon(join(var.iconpath, 'missing.svg'))
|
||||
icon = QIcon(join(var.iconpath, 'missing.svg'))
|
||||
|
||||
return QIcon(filename)
|
||||
icon = QIcon(filename)
|
||||
|
||||
if size:
|
||||
icon = QIcon(icon.pixmap(16))
|
||||
|
||||
return icon
|
||||
|
||||
|
||||
def AddShortcut(key, action, widget):
|
||||
|
@ -245,10 +250,13 @@ def Decode(byte):
|
|||
|
||||
## subclass QMenu because there's no way to get the number of items
|
||||
class Menu(QMenu):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
def __init__(self, parent, title=None):
|
||||
super().__init__(parent)
|
||||
self.count = 0
|
||||
|
||||
if title:
|
||||
self.setTitle(title)
|
||||
|
||||
def AddAction(self, name, callback):
|
||||
self.addAction(name, callback)
|
||||
self.count += 1
|
||||
|
@ -312,13 +320,17 @@ def ParseSoundcloudInfo(data):
|
|||
|
||||
|
||||
def ExceptionHandler(exctype, value, tb):
|
||||
lines = [line for line in traceback.format_exception(exctype, value, tb)]
|
||||
sys._excepthook(exctype, value, tb)
|
||||
|
||||
if lines[-1] in ['\n', '\n ']:
|
||||
lines.remove(lines)
|
||||
# Apparently the line above is enough to not bring down the whole browser
|
||||
# Gonna keep custom handler here for now though
|
||||
#lines = [line for line in traceback.format_exception(exctype, value, tb)]
|
||||
|
||||
error = ''.join(lines)
|
||||
print(f'\n------------\n{error}------------')
|
||||
#if lines[-1] in ['\n', '\n ']:
|
||||
#lines.remove(lines)
|
||||
|
||||
#error = ''.join(lines)
|
||||
#print(f'\n------------\n{error}------------')
|
||||
|
||||
|
||||
TextCodec = QTextCodec.codecForMib(106)
|
||||
|
|
198
qtweb/main.py
198
qtweb/main.py
|
@ -1,26 +1,25 @@
|
|||
import sys, os, time, json, signal, asyncio, tracemalloc
|
||||
import sys, os, json, signal, asyncio, tracemalloc
|
||||
|
||||
from optparse import OptionParser
|
||||
from urllib.parse import urlencode, urlparse, quote_plus
|
||||
from urllib.parse import urlparse, quote_plus
|
||||
from os.path import join, abspath
|
||||
from base64 import b64encode, b64decode
|
||||
from pathlib import Path
|
||||
|
||||
from .Lib.IzzyLib import logging
|
||||
from .Lib.IzzyLib.misc import boolean
|
||||
|
||||
from . import isWindows, isLinux, debstable, dialogs, tabs, __version__
|
||||
from . import isWindows, debstable, dialogs, tabs, __version__
|
||||
from .urlhandlers import LocalHandler, RegisterScheme
|
||||
from .webview import WebEngineView
|
||||
from .profile import WebEngineProfile
|
||||
from .config import var
|
||||
from .database import db, get, put
|
||||
from .mastodon import Mastodon
|
||||
from .mbus import Client, Server
|
||||
from .themes import SetupThemes, ChangeTheme
|
||||
from .themes import ColorTheme
|
||||
from .arguments import args
|
||||
from .functions import (
|
||||
Icon, AddShortcut, UserAgentGen,
|
||||
ExceptionHandler, PrintMethods, Notifications, Menu
|
||||
ExceptionHandler, Notifications, Menu
|
||||
)
|
||||
|
||||
|
||||
|
@ -42,6 +41,7 @@ from PyQt5 import uic
|
|||
|
||||
|
||||
## Prevent errors from bringing down the whole browser
|
||||
sys._excepthook = sys.excepthook
|
||||
sys.excepthook = ExceptionHandler
|
||||
|
||||
logging.setConfig({'level': get.config('loglevel', 'INFO')})
|
||||
|
@ -62,11 +62,15 @@ class Browser(QMainWindow):
|
|||
else:
|
||||
self.snapshot = None
|
||||
|
||||
SetupThemes(app)
|
||||
if not debstable:
|
||||
RegisterScheme(var.local)
|
||||
|
||||
db.window = self
|
||||
|
||||
self.jsdebug = False
|
||||
self.darktheme = True if get.config('darktheme') in [1, '1'] else False
|
||||
self.app = app
|
||||
self.default_style = app.style().objectName().lower()
|
||||
self.default_palette = app.style().standardPalette()
|
||||
self.themes = ColorTheme(self)
|
||||
self.clipboard = app.clipboard()
|
||||
self.threadpool = QThreadPool()
|
||||
self.notif = Notifications()
|
||||
|
@ -77,7 +81,7 @@ class Browser(QMainWindow):
|
|||
'y': 100,
|
||||
'maximized': True
|
||||
}
|
||||
|
||||
|
||||
self.statedata.update(json.loads(get.config('state', "{}")))
|
||||
|
||||
## Setup empty variables for use later
|
||||
|
@ -86,17 +90,23 @@ class Browser(QMainWindow):
|
|||
self.socket = None
|
||||
self.urlhover = None
|
||||
self.fullscreen = False
|
||||
self.shutdown = False
|
||||
self.widgettabs = {}
|
||||
self.open_dialogs = {}
|
||||
|
||||
WebEngineProfile(self)
|
||||
|
||||
#app.setStyle('fusion')
|
||||
#ChangeTheme()
|
||||
self.profile = WebEngineProfile(self)
|
||||
self.local_scheme_handler = LocalHandler(self)
|
||||
|
||||
#logging.setConfig({'systemnotif': self.notif})
|
||||
|
||||
if self.darktheme:
|
||||
ChangeTheme('dark')
|
||||
theme = get.config('theme', 'Default')
|
||||
|
||||
#app.setStyle('fusion')
|
||||
#self.themes.ChangeTheme()
|
||||
|
||||
# Re-enable when color themes are fixed
|
||||
#if theme != 'Default':
|
||||
#self.themes.ChangeTheme(theme)
|
||||
|
||||
self.ui = uic.loadUi(join(var.resources, 'window.ui'))
|
||||
self.setCentralWidget(self.ui)
|
||||
|
@ -142,14 +152,15 @@ class Browser(QMainWindow):
|
|||
self.ui.toot.clicked.connect(lambda : self._open_dialog('toot'))
|
||||
|
||||
## Keyboard shortcuts
|
||||
AddShortcut('Ctrl+L', self._focus_urlbar, self.ui.url)
|
||||
AddShortcut('Ctrl+T', lambda *args: self.NewWebTab(switch=True), self.ui)
|
||||
AddShortcut('Ctrl+R', lambda *args: self.ui.tabs.currentWidget().reload(), self.ui)
|
||||
AddShortcut('Ctrl+W', lambda *args: self.CloseTab(), self.ui)
|
||||
AddShortcut('Ctrl+N', lambda *args: self.NewWebTab('https://www.youtube.com/watch?v=dQw4w9WgXcQ', switch=True), self.ui)
|
||||
AddShortcut('Ctrl+F', lambda *args: self.ui.tabs.currentWidget().searchbar.Search('toggle'), self.ui)
|
||||
AddShortcut('F3', lambda *args: self.ui.tabs.currentWidget().searchbar.Search('toggle'), self.ui)
|
||||
AddShortcut('F11', lambda *args: self.Fullscreen(), self.ui)
|
||||
AddShortcut('Ctrl+L', self._focus_urlbar, self)
|
||||
AddShortcut('Ctrl+T', lambda *args: self.NewWebTab(switch=True), self)
|
||||
AddShortcut('Ctrl+R', lambda *args: self.ui.tabs.currentWidget().reload(), self)
|
||||
AddShortcut('Ctrl+W', lambda *args: self.CloseTab(), self)
|
||||
AddShortcut('Ctrl+N', lambda *args: self.NewWebTab('https://www.youtube.com/watch?v=dQw4w9WgXcQ', switch=True), self)
|
||||
AddShortcut('Ctrl+F', lambda *args: self.ui.tabs.currentWidget().searchbar.Search('toggle'), self)
|
||||
AddShortcut('F3', lambda *args: self.ui.tabs.currentWidget().searchbar.Search('toggle'), self)
|
||||
AddShortcut('F5', lambda *args: self.ui.tabs.currentWidget().reload(), self)
|
||||
AddShortcut('F11', lambda *args: self.Fullscreen(), self)
|
||||
|
||||
# keeping this here for testing purposes
|
||||
#self.profile.setHttpUserAgent('Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0')
|
||||
|
@ -162,13 +173,8 @@ class Browser(QMainWindow):
|
|||
for row in db.fetch('tabs', sort='tabid', single=False):
|
||||
self.NewWebTab(row.url)
|
||||
|
||||
try:
|
||||
activetab = int(get.config('activetab', 0))
|
||||
self.ui.tabs.setCurrentIndex(activetab)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
activetab = int(get.config('activetab', 0))
|
||||
self.ui.tabs.setCurrentIndex(activetab)
|
||||
self._prevent_empty_tabview()
|
||||
|
||||
## Restore the window position and size
|
||||
|
@ -203,49 +209,14 @@ class Browser(QMainWindow):
|
|||
self.ui.url.selectAll()
|
||||
|
||||
|
||||
def _close_window(self, event=None):
|
||||
lock = Path(var.lock)
|
||||
opentabs = []
|
||||
tabrange = list(reversed(range(0, self.ui.tabs.count())))
|
||||
put.config('activetab', str(self.ui.tabs.currentIndex()))
|
||||
self.SaveWinState()
|
||||
|
||||
for tabid in ([0] if len(tabrange) < 1 else tabrange):
|
||||
widget = self.ui.tabs.widget(tabid)
|
||||
|
||||
if widget.windowTitle():
|
||||
continue
|
||||
|
||||
title = widget.title()
|
||||
url = widget.url().toString()
|
||||
|
||||
opentabs.append(url)
|
||||
put.tab(tabid, url, title)
|
||||
|
||||
self.CloseTab(tabid, shutdown=True)
|
||||
|
||||
for row in db.fetch('tabs', single=False):
|
||||
if row.url not in opentabs:
|
||||
db.remove('tabs', row.id)
|
||||
|
||||
db.close()
|
||||
logging.verbose('Saved state and tabs. Exiting...')
|
||||
|
||||
for srv in [self.server, self.socket]:
|
||||
if srv:
|
||||
srv.stop()
|
||||
|
||||
if event:
|
||||
event.accept()
|
||||
|
||||
if lock.exists():
|
||||
lock.unlink()
|
||||
|
||||
|
||||
def _button_click(self, button):
|
||||
widget = self.ui.tabs.currentWidget()
|
||||
homepage = get.config('homepage', 'https://ddg.gg')
|
||||
|
||||
if button == 'newtab':
|
||||
self.NewWebTab(switch=True)
|
||||
return
|
||||
|
||||
if hasattr(widget, 'LoadUrl'):
|
||||
actions = {
|
||||
'back': {'cmd': widget.back},
|
||||
|
@ -253,7 +224,6 @@ class Browser(QMainWindow):
|
|||
'stop': {'cmd': widget.stop},
|
||||
'refresh': {'cmd': widget.reload},
|
||||
'home': {'cmd': widget.LoadUrl, 'args': [homepage]},
|
||||
'newtab': {'cmd': self.NewWebTab, 'kwargs': {'switch': True}},
|
||||
'go': {'cmd': widget.LoadUrl, 'args': [self.ui.url.text()]}
|
||||
}
|
||||
|
||||
|
@ -277,8 +247,10 @@ class Browser(QMainWindow):
|
|||
logging.error('No mastodon accounts')
|
||||
return
|
||||
|
||||
widget = dialogs.Toot(self, self.mastodon)
|
||||
widget.show()
|
||||
widget = self.open_dialogs.get(dialog)
|
||||
|
||||
if widget:
|
||||
widget.activateWindow()
|
||||
return
|
||||
|
||||
webview = self.ui.tabs.currentWidget()
|
||||
|
@ -292,6 +264,10 @@ class Browser(QMainWindow):
|
|||
'siteedit': {
|
||||
'cmd': dialogs.SiteSettings,
|
||||
'args': [webview.url().host()]
|
||||
},
|
||||
'toot': {
|
||||
'cmd': dialogs.Toot,
|
||||
'args': [self]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +276,8 @@ class Browser(QMainWindow):
|
|||
if not action:
|
||||
return
|
||||
|
||||
action['cmd'](*action.get('args', []), **action.get('kwargs', {})).ui.show()
|
||||
self.open_dialogs[dialog] = action['cmd'](self, *action.get('args', []), **action.get('kwargs', {}))
|
||||
self.open_dialogs[dialog].show()
|
||||
|
||||
|
||||
def _update_webaction_buttons(self, name=None, state=None):
|
||||
|
@ -360,6 +337,55 @@ class Browser(QMainWindow):
|
|||
self.NewWebTab()
|
||||
|
||||
|
||||
def closeEvent(self, event=None):
|
||||
## Make sure this function only fires once
|
||||
if self.shutdown:
|
||||
return
|
||||
|
||||
self.shutdown = True
|
||||
|
||||
if event:
|
||||
event.accept()
|
||||
|
||||
lock = Path(var.lock)
|
||||
opentabs = []
|
||||
tabrange = list(reversed(range(0, self.ui.tabs.count())))
|
||||
put.config('activetab', str(self.ui.tabs.currentIndex()))
|
||||
self.SaveWinState()
|
||||
|
||||
for tabid in ([0] if len(tabrange) < 1 else tabrange):
|
||||
widget = self.ui.tabs.widget(tabid)
|
||||
|
||||
if widget.windowTitle():
|
||||
continue
|
||||
|
||||
title = widget.title()
|
||||
url = widget.url().toString()
|
||||
|
||||
if widget.devpage.view:
|
||||
widget.devpage.closeEvent()
|
||||
widget.devpage.destroy()
|
||||
|
||||
opentabs.append(url)
|
||||
put.tab(tabid, url, title)
|
||||
|
||||
self.CloseTab(tabid, shutdown=True)
|
||||
|
||||
for row in db.fetch('tabs', single=False):
|
||||
if row.url not in opentabs:
|
||||
db.remove('tabs', row.id)
|
||||
|
||||
db.close()
|
||||
logging.verbose('Saved state and tabs. Exiting...')
|
||||
|
||||
for srv in [self.server, self.socket]:
|
||||
if srv:
|
||||
srv.stop()
|
||||
|
||||
if lock.exists():
|
||||
lock.unlink()
|
||||
|
||||
|
||||
def SaveWinState(self, width=None, height=None, x=None, y=None):
|
||||
winstate = self.windowState() in [Qt.WindowActive, Qt.WindowNoState]
|
||||
maximized = self.windowState() == Qt.WindowMaximized
|
||||
|
@ -413,10 +439,7 @@ class Browser(QMainWindow):
|
|||
|
||||
|
||||
def NewWebTab(self, url=None, switch=False, nexttab=False):
|
||||
#layout = QVBoxLayout()
|
||||
webview = WebEngineView(self, url)
|
||||
#layout.addWidget(webview.search)
|
||||
#layout.addWidget(webview)
|
||||
webview = WebEngineView(self, url if url else get.config('homepage', 'https://ddg.gg'))
|
||||
|
||||
if nexttab and get.config('nexttab', True):
|
||||
index = self.ui.tabs.currentIndex() + 1
|
||||
|
@ -429,6 +452,10 @@ class Browser(QMainWindow):
|
|||
index = self.ui.tabs.indexOf(webview)
|
||||
self.ui.tabs.setCurrentIndex(index)
|
||||
|
||||
if not url:
|
||||
self.ui.url.setFocus()
|
||||
self.ui.url.selectAll()
|
||||
|
||||
return webview
|
||||
|
||||
|
||||
|
@ -489,6 +516,7 @@ class Browser(QMainWindow):
|
|||
|
||||
if not shutdown:
|
||||
self._prevent_empty_tabview()
|
||||
self.ui.tabs.currentWidget().setFocus()
|
||||
|
||||
|
||||
class UrlBarEsc(QObject):
|
||||
|
@ -523,6 +551,11 @@ class TabBar(QTabBar):
|
|||
self.setDocumentMode(True)
|
||||
self.window = window
|
||||
|
||||
self.setStyleSheet('''
|
||||
QTabBar::tab:selected {font: bold;}
|
||||
QTabBar::tab-bar {alignment: center;}
|
||||
''')
|
||||
|
||||
## Set tabs to even take up full width
|
||||
def tabSizeHint(self, index):
|
||||
compensation = 0 #I'll need this later
|
||||
|
@ -586,6 +619,11 @@ def main():
|
|||
app.setOrganizationDomain('barkshark.xyz')
|
||||
app.setWindowIcon(Icon('icon'))
|
||||
|
||||
if get.config('remotedebug', False):
|
||||
debugport = get.config('remotedebugport', '8018')
|
||||
debughost = 'still gotta sort this out'
|
||||
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = f'127.0.0.1:{remotedebugport}'
|
||||
|
||||
host = get.config('mhost', 'localhost')
|
||||
port = get.config('mport', 8008)
|
||||
|
||||
|
@ -616,7 +654,7 @@ def main():
|
|||
|
||||
window = Browser(app)
|
||||
window.server = Server(window)
|
||||
app.aboutToQuit.connect(window._close_window)
|
||||
app.aboutToQuit.connect(window.close)
|
||||
|
||||
if not isWindows:
|
||||
window.socket = Server(window, True)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import json, shutil
|
||||
|
||||
from urllib import request
|
||||
from urllib.parse import urlparse, urlencode
|
||||
from urllib.error import HTTPError
|
||||
from urllib.parse import urlparse
|
||||
from os.path import join, isfile, basename
|
||||
from os import makedirs, remove
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import asyncio, socket, json, sys, traceback, tracemalloc, argparse, datetime, time, linecache
|
||||
import asyncio, socket, json, sys, traceback, tracemalloc, argparse, datetime, linecache
|
||||
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
|
@ -78,7 +78,10 @@ class Server(object):
|
|||
self.loop.close()
|
||||
|
||||
if self.socket:
|
||||
Path(self.socket).unlink()
|
||||
sock = Path(self.socket)
|
||||
|
||||
if sock.exists():
|
||||
sock.unlink()
|
||||
|
||||
|
||||
def restart(self):
|
||||
|
@ -136,8 +139,16 @@ class Server(object):
|
|||
self.scinfo = ParseSoundcloudInfo(value)
|
||||
|
||||
|
||||
async def search(self, *args, **kwargs):
|
||||
self.GetWebview().search.Search(*args, **kwargs)
|
||||
async def search(self, *args):
|
||||
searchbar = self.GetWebview().searchbar
|
||||
|
||||
if not args:
|
||||
searchbar.Search('reset')
|
||||
searchbar.hide()
|
||||
return
|
||||
|
||||
searchbar.Search(text=' '.join(args))
|
||||
searchbar.show()
|
||||
|
||||
|
||||
async def new_tab(self, *args, **kwargs):
|
||||
|
@ -219,9 +230,8 @@ class Server(object):
|
|||
def trace_top(self, num=15, key_type='lineno'):
|
||||
if not self.window.snapshot:
|
||||
self.trace_snapshot()
|
||||
snapshot = self.window.snapshot
|
||||
|
||||
snapshot = snapshot.filter_traces((
|
||||
snapshot = self.window.snapshot.filter_traces((
|
||||
tracemalloc.Filter(False, '<frozen importlib._bootstrap>'),
|
||||
tracemalloc.Filter(False, '<unknown>'),
|
||||
))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import threading, sys, os, time
|
||||
import threading, sys, os
|
||||
|
||||
from datetime import datetime
|
||||
from os.path import join
|
||||
|
@ -10,12 +10,12 @@ from . import pyqtver, debstable, isWindows
|
|||
from . import dialogs
|
||||
from .config import var
|
||||
from .database import db, get, put, delete
|
||||
from .functions import useragent, GetSoftware, httpclient, Decode, psl, DateTime, MD5Check
|
||||
from .functions import useragent, GetSoftware, httpclient, Decode, psl, MD5Check
|
||||
|
||||
from PyQt5.QtWebEngineWidgets import *
|
||||
from PyQt5.QtCore import QUrl, QDateTime
|
||||
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
|
||||
from PyQt5.QtNetwork import QNetworkCookie, QNetworkCookieJar
|
||||
from PyQt5.QtNetwork import QNetworkCookie
|
||||
|
||||
|
||||
AddHeader = lambda info, k, v: info.setHttpHeader(k.encode(), v.encode())
|
||||
|
@ -44,9 +44,6 @@ blockedURL = {
|
|||
'facebook.com': [
|
||||
'/tr',
|
||||
'/brandlift.php'
|
||||
],
|
||||
'twitch.tv': [
|
||||
'/service-worker.js'
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -55,7 +52,6 @@ class WebEngineProfile(QWebEngineProfile):
|
|||
def __init__(self, parent):
|
||||
super().__init__(var.profile)
|
||||
|
||||
parent.profile = self
|
||||
self.interceptor = WebFilter(parent)
|
||||
self.window = parent
|
||||
self.notif = parent.notif
|
||||
|
@ -161,15 +157,6 @@ class WebEngineProfile(QWebEngineProfile):
|
|||
return True
|
||||
|
||||
|
||||
def _new_cookie(self, cookie):
|
||||
if not cookie.isSessionCookie():
|
||||
put.cookie(cookie)
|
||||
|
||||
|
||||
def _rem_cookie(self, cookie):
|
||||
delete.cookie(cookie)
|
||||
|
||||
|
||||
def LoadCookies(self):
|
||||
for cookie in get.cookie():
|
||||
self.cookieStore().setCookie(cookie)
|
||||
|
@ -210,23 +197,22 @@ class WebFilter(QWebEngineUrlRequestInterceptor):
|
|||
return
|
||||
|
||||
## Check if domain is a mastodon instance
|
||||
if not pagerow.domain and not pagerow.mastodon and not any(map(requrl.toString().startswith, ['about:', 'chrome://'])):
|
||||
if not pagedomain:
|
||||
return
|
||||
if get.config('mastocheck', False):
|
||||
if not pagerow.domain and not pagerow.mastodon and not any(map(requrl.toString().startswith, ['about:', 'chrome://'])):
|
||||
if not pagedomain:
|
||||
return
|
||||
|
||||
if self.threads.get(pagedomain):
|
||||
return
|
||||
if self.threads.get(pagedomain):
|
||||
return
|
||||
|
||||
self.threads[pagedomain] = threading.Thread(target=GetSoftware, args=[pagedomain])
|
||||
self.threads[pagedomain].start()
|
||||
logging.verbose('Checking for presence of nodeinfo')
|
||||
self.threads[pagedomain] = threading.Thread(target=GetSoftware, args=[pagedomain])
|
||||
self.threads[pagedomain].start()
|
||||
|
||||
## Delete the thread object once it's finished
|
||||
elif self.threads.get(pagedomain):
|
||||
del self.threads[pagedomain]
|
||||
## Delete the thread object once it's finished
|
||||
elif self.threads.get(pagedomain):
|
||||
del self.threads[pagedomain]
|
||||
|
||||
## Set custom headers
|
||||
AddHeader(info, 'X-Trans-Rights', 'Are Human Rights')
|
||||
|
||||
## Google is a fuck and is very picky about what browsers are supported
|
||||
#if 'google.com' in [pagetopdomain, reqtopdomain]:
|
||||
#info.setHttpHeader('user-agent'.encode(), 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0'.encode())
|
||||
# This breaks gmx.com
|
||||
#AddHeader(info, 'X-Trans-Rights', 'Are Human Rights')
|
||||
|
|
109
qtweb/resources/dialog-authentication.ui
Normal file
109
qtweb/resources/dialog-authentication.ui
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>479</width>
|
||||
<height>292</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="username"/>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="savepass">
|
||||
<property name="statusTip">
|
||||
<string>Does nothing rn</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QPushButton" name="login">
|
||||
<property name="text">
|
||||
<string>Login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>169</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QPushButton" name="cancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QLabel" name="realm">
|
||||
<property name="text">
|
||||
<string>Authentication requested from {host}. Server message: {msg}</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>username</tabstop>
|
||||
<tabstop>password</tabstop>
|
||||
<tabstop>savepass</tabstop>
|
||||
<tabstop>cancel</tabstop>
|
||||
<tabstop>login</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
115
qtweb/resources/dialog-bookmark.ui
Normal file
115
qtweb/resources/dialog-bookmark.ui
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>568</width>
|
||||
<height>447</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="titlelabel">
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="urllabel">
|
||||
<property name="text">
|
||||
<string>Url</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="categorylabel">
|
||||
<property name="text">
|
||||
<string>Category</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="category"/>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="descriptionlabel">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="4">
|
||||
<widget class="QPlainTextEdit" name="description">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>230</width>
|
||||
<height>170</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QPushButton" name="discard">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QPushButton" name="remove">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="5">
|
||||
<widget class="QPushButton" name="save">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="url">
|
||||
<property name="maxLength">
|
||||
<number>2048</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="title"/>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>228</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,21 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>324</width>
|
||||
<height>345</height>
|
||||
<height>434</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>324</width>
|
||||
|
@ -29,15 +23,32 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="discard">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
|
@ -52,7 +63,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>316</width>
|
||||
<height>304</height>
|
||||
<height>393</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
|
@ -179,6 +190,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="mastodon">
|
||||
<property name="toolTip">
|
||||
<string>Is this domain a mastodon instance? Hint: Enable 'Auto-detect Mastodon instances' under advanced settings to enable auto-detection</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Mastodon Instance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -196,39 +217,6 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="discard">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="reset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="save">
|
||||
<property name="text">
|
||||
|
@ -242,23 +230,18 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="reset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>adblock</tabstop>
|
||||
<tabstop>allowhttp</tabstop>
|
||||
<tabstop>fullscreen</tabstop>
|
||||
<tabstop>cookies</tabstop>
|
||||
<tabstop>notifications</tabstop>
|
||||
<tabstop>capture</tabstop>
|
||||
<tabstop>microphone</tabstop>
|
||||
<tabstop>location</tabstop>
|
||||
<tabstop>camera</tabstop>
|
||||
<tabstop>discard</tabstop>
|
||||
<tabstop>reset</tabstop>
|
||||
<tabstop>save</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,44 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>486</width>
|
||||
<height>306</height>
|
||||
<width>516</width>
|
||||
<height>337</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="6">
|
||||
<widget class="QLabel" name="replytext">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="6">
|
||||
<widget class="QLineEdit" name="warning">
|
||||
<property name="placeholderText">
|
||||
|
@ -46,57 +21,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="6">
|
||||
<widget class="QPlainTextEdit" name="content">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="backgroundVisible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Message body</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="count">
|
||||
<property name="text">
|
||||
<string>500</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="account"/>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QComboBox" name="privacy">
|
||||
<item>
|
||||
|
@ -121,16 +45,6 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="cancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<widget class="QPushButton" name="post">
|
||||
<property name="text">
|
||||
|
@ -141,16 +55,85 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="account"/>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="cancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="6">
|
||||
<widget class="QLabel" name="replytext">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="count">
|
||||
<property name="text">
|
||||
<string>500</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="6">
|
||||
<widget class="QPlainTextEdit" name="content">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="backgroundVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Message body</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>warning</tabstop>
|
||||
<tabstop>content</tabstop>
|
||||
<tabstop>account</tabstop>
|
||||
<tabstop>privacy</tabstop>
|
||||
<tabstop>cancel</tabstop>
|
||||
<tabstop>post</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
BIN
qtweb/resources/dictionaries/en-US.bdict
Normal file
BIN
qtweb/resources/dictionaries/en-US.bdict
Normal file
Binary file not shown.
|
@ -1,149 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>467</width>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="4">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="urllabel">
|
||||
<property name="text">
|
||||
<string>Url</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="url">
|
||||
<property name="maxLength">
|
||||
<number>2048</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="categorylabel">
|
||||
<property name="text">
|
||||
<string>Category</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="category"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="descriptionlabel">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPlainTextEdit" name="description">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>230</width>
|
||||
<height>170</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="title"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="titlelabel">
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>198</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="discard">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="remove">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="save">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>title</tabstop>
|
||||
<tabstop>url</tabstop>
|
||||
<tabstop>category</tabstop>
|
||||
<tabstop>description</tabstop>
|
||||
<tabstop>discard</tabstop>
|
||||
<tabstop>remove</tabstop>
|
||||
<tabstop>save</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
62
qtweb/resources/tab-downloads.ui
Normal file
62
qtweb/resources/tab-downloads.ui
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>481</width>
|
||||
<height>418</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="resume">
|
||||
<property name="text">
|
||||
<string>Resume All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="clear">
|
||||
<property name="text">
|
||||
<string>Clear Finished</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="pause">
|
||||
<property name="text">
|
||||
<string>Pause All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="5">
|
||||
<widget class="QListView" name="downloads">
|
||||
<property name="viewMode">
|
||||
<enum>QListView::ListMode</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>677</width>
|
||||
<height>420</height>
|
||||
<width>696</width>
|
||||
<height>489</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -30,7 +30,7 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<widget class="QTabWidget" name="tabs">
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::West</enum>
|
||||
</property>
|
||||
|
@ -42,52 +42,6 @@
|
|||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="heckinfuck">
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="hidetabs">
|
||||
<property name="toolTip">
|
||||
<string>Hide the tab bar when only one tab is open</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto-hide tabs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QSpinBox" name="cachesize">
|
||||
<property name="toolTip">
|
||||
<string>Size in mebibytes of the web cache</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>8096</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Homepage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="homepage">
|
||||
<property name="toolTip">
|
||||
<string>The default web page to load in a new tab</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>2048</number>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
|
@ -95,61 +49,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QCheckBox" name="adblock">
|
||||
<property name="toolTip">
|
||||
<string>Block ads on web pages. Can be turned off for individual sites</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable ad blocker</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QCheckBox" name="darktheme">
|
||||
<property name="toolTip">
|
||||
<string>Set the browser to a dark theme. Does not affect web pages</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use dark theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QPushButton" name="selectdownloaddir">
|
||||
<property name="text">
|
||||
<string>Pick Directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cache Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="downloaddir">
|
||||
<property name="toolTip">
|
||||
<string>Default location for downloads</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="createdownloaddir">
|
||||
<property name="text">
|
||||
<string>Create Dir</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="4">
|
||||
<item row="10" column="0" colspan="4">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
|
@ -183,19 +83,232 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="1" colspan="3">
|
||||
<spacer name="verticalSpacer">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="downloaddir">
|
||||
<property name="toolTip">
|
||||
<string>Default location for downloads</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Homepage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cache Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QSpinBox" name="cachesize">
|
||||
<property name="toolTip">
|
||||
<string>Size in mebibytes of the web cache</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>8096</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="createdownloaddir">
|
||||
<property name="text">
|
||||
<string>Create Dir</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="homepage">
|
||||
<property name="toolTip">
|
||||
<string>The default web page to load in a new tab</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>2048</number>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QPushButton" name="selectdownloaddir">
|
||||
<property name="text">
|
||||
<string>Pick Directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="nitter">
|
||||
<property name="toolTip">
|
||||
<string>Redirect Twitter links to a Nitter instance</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Nitter redirect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="nitterurl">
|
||||
<property name="placeholderText">
|
||||
<string>ex. https://nitter.net</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="nitterreset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="hidetabs">
|
||||
<property name="toolTip">
|
||||
<string>Hide the tab bar when only one tab is open</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto-hide tabs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="adblock">
|
||||
<property name="toolTip">
|
||||
<string>Block ads on web pages by denying hosts. Can be turned off for individual sites</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable ad blocker</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="reusetab">
|
||||
<property name="toolTip">
|
||||
<string>If a web page tries to create a new tab, use the current tab instead</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reuse tabs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="4">
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>638</width>
|
||||
<height>219</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Soundcloud</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="screpost">
|
||||
<property name="toolTip">
|
||||
<string>Remove all reposts from the Stream page
|
||||
Note: Reposts will still be added to the playlist, but won't be displayed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove Reposts</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="appearance">
|
||||
<attribute name="title">
|
||||
<string>Appearance</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="themedelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="themenew">
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="themeedit">
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="5">
|
||||
<widget class="QListWidget" name="theme">
|
||||
<property name="uniformItemSizes">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="search">
|
||||
|
@ -325,48 +438,13 @@
|
|||
<string>Mastodon</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Domain</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="7">
|
||||
<widget class="QPushButton" name="login">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item row="3" column="6">
|
||||
<widget class="QPushButton" name="reset">
|
||||
<property name="toolTip">
|
||||
<string>Attempt to login to the account</string>
|
||||
<string>Empty the form fields</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="7">
|
||||
<widget class="QPushButton" name="logout">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Logout of the selected account</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Logout</string>
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -380,27 +458,22 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="7">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
<item row="5" column="7">
|
||||
<widget class="QPushButton" name="logout">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>E-Mail</string>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="6">
|
||||
<widget class="QPushButton" name="reset">
|
||||
<property name="toolTip">
|
||||
<string>Empty the form fields</string>
|
||||
<string>Logout of the selected account</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
<string>Logout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -472,6 +545,9 @@
|
|||
</item>
|
||||
<item row="5" column="6">
|
||||
<widget class="QPushButton" name="mdefault">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -486,10 +562,32 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<item row="3" column="7">
|
||||
<widget class="QPushButton" name="login">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Attempt to login to the account</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
<string>Login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Domain</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -509,8 +607,25 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="7">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="5">
|
||||
<widget class="QPushButton" name="refresh">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -525,6 +640,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>E-Mail</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="advanced">
|
||||
|
@ -532,95 +654,10 @@
|
|||
<string>Advanced</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="mbushost">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The host MBus listens on</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>127.0.0.1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0.0.0.0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>False</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<item row="2" column="3">
|
||||
<widget class="QPushButton" name="logreset">
|
||||
<property name="text">
|
||||
<string>MBus Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="mbusport">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The port MBus listens on</string>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1024</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>25565</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8008</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Stdout Log Level</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="jsdebug">
|
||||
<property name="text">
|
||||
<string>Send JS output to stdout</string>
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -664,26 +701,6 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>MBus Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="portreset">
|
||||
<property name="sizePolicy">
|
||||
|
@ -697,6 +714,77 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="mbusport">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The port MBus listens on</string>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1024</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>25565</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8008</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="mbushost">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The host MBus listens on</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>127.0.0.1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>0.0.0.0</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>False</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="hostreset">
|
||||
<property name="sizePolicy">
|
||||
|
@ -717,12 +805,18 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QPushButton" name="logreset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
<item row="7" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="automd5">
|
||||
|
@ -734,6 +828,44 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>MBus Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Stdout Log Level</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="jsdebug">
|
||||
<property name="text">
|
||||
<string>Send JS output to stdout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>MBus Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="mastocheck">
|
||||
<property name="toolTip">
|
||||
<string>Query nodeinfo on previously unvisited sites to check if the domain is a mastodon instance</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto-detect Mastodon instances</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -741,7 +873,7 @@
|
|||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>tabs</tabstop>
|
||||
<tabstop>homepage</tabstop>
|
||||
<tabstop>cachesize</tabstop>
|
||||
<tabstop>downloaddir</tabstop>
|
||||
|
@ -749,9 +881,18 @@
|
|||
<tabstop>selectdownloaddir</tabstop>
|
||||
<tabstop>hidetabs</tabstop>
|
||||
<tabstop>adblock</tabstop>
|
||||
<tabstop>darktheme</tabstop>
|
||||
<tabstop>sdefault</tabstop>
|
||||
<tabstop>reusetab</tabstop>
|
||||
<tabstop>nitter</tabstop>
|
||||
<tabstop>nitterurl</tabstop>
|
||||
<tabstop>nitterreset</tabstop>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>screpost</tabstop>
|
||||
<tabstop>setdefault</tabstop>
|
||||
<tabstop>themenew</tabstop>
|
||||
<tabstop>themeedit</tabstop>
|
||||
<tabstop>themedelete</tabstop>
|
||||
<tabstop>theme</tabstop>
|
||||
<tabstop>sdefault</tabstop>
|
||||
<tabstop>snew</tabstop>
|
||||
<tabstop>sdelete</tabstop>
|
||||
<tabstop>sengines</tabstop>
|
||||
|
@ -772,6 +913,8 @@
|
|||
<tabstop>logreset</tabstop>
|
||||
<tabstop>jsdebug</tabstop>
|
||||
<tabstop>tracemalloc</tabstop>
|
||||
<tabstop>automd5</tabstop>
|
||||
<tabstop>mastocheck</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
|
@ -8,3 +8,23 @@ function QtWebGetInfo() {
|
|||
|
||||
return artist + ':::' + artistLink + ':::' + title + ':::' + titleLink + ':::' + progress + ':::' + length
|
||||
}
|
||||
|
||||
|
||||
// https://greasyfork.org/en/scripts/27012-soundcloud-hide-reposts
|
||||
// ==UserScript==
|
||||
// @name SoundCloud hide reposts
|
||||
// @namespace http://abs.ezw.me
|
||||
// @version 1.2
|
||||
// @author ABS
|
||||
// @description Only see new songs in your SoundCloud stream
|
||||
// @match *://soundcloud.com/stream
|
||||
// ==/UserScript==
|
||||
|
||||
function norepost(){
|
||||
for (let repost of document.getElementsByClassName("soundList__item")) {
|
||||
if (repost.getElementsByClassName("sc-ministats-reposts").length > 0)
|
||||
repost.remove();
|
||||
console.log(repost);
|
||||
}
|
||||
}
|
||||
|
170
qtweb/tabs.py
170
qtweb/tabs.py
|
@ -1,16 +1,15 @@
|
|||
import re, json
|
||||
|
||||
from pathlib import Path, PurePosixPath, PureWindowsPath
|
||||
from pathlib import Path
|
||||
from os.path import join, isfile, abspath
|
||||
from urllib.parse import urlparse
|
||||
from configparser import ConfigParser
|
||||
|
||||
from . import isLinux, isWindows
|
||||
from .config import var
|
||||
from . import isWindows
|
||||
from .config import var, default
|
||||
from .database import db, put, get, delete
|
||||
from .functions import Icon, NewDesktopEntry
|
||||
from .dialogs import EditBookmark
|
||||
from .themes import ChangeTheme
|
||||
|
||||
from .Lib.IzzyLib import logging
|
||||
from .Lib.IzzyLib.misc import boolean
|
||||
|
@ -23,7 +22,7 @@ from PyQt5 import uic
|
|||
|
||||
class Bookmarks(object):
|
||||
def __init__(self, window):
|
||||
self.ui = uic.loadUi(join(var.resources, 'bookmarktab.ui'))
|
||||
self.ui = uic.loadUi(join(var.resources, 'tab-bookmarks.ui'))
|
||||
self.title = 'Bookmarks'
|
||||
self.url = self.title
|
||||
self.window = window
|
||||
|
@ -34,7 +33,7 @@ class Bookmarks(object):
|
|||
self.ui.refresh.clicked.connect(lambda *args: self._row_action('refresh'))
|
||||
self.ui.table.cellDoubleClicked.connect(lambda *args: self._row_action('edit'))
|
||||
|
||||
for size in [(0, 150), (1, 350), (2, 80)]:
|
||||
for size in [(0, 350), (1, 200), (2, 80)]:
|
||||
self.ui.table.setColumnWidth(*size)
|
||||
|
||||
self._populate_table()
|
||||
|
@ -106,18 +105,24 @@ class History(object):
|
|||
|
||||
class Preferences(object):
|
||||
def __init__(self, window):
|
||||
self.ui = uic.loadUi(join(var.resources, 'preferences.ui'))
|
||||
self.ui = uic.loadUi(join(var.resources, 'tab-preferences.ui'))
|
||||
self.title = 'Preferences'
|
||||
self.window = window
|
||||
|
||||
dldir = get.config('dlpath', var.downloadpath)
|
||||
nitter_state = get.config('nitter', 0)
|
||||
|
||||
## General tab
|
||||
self.ui.homepage.setText(get.config('homepage', 'http://ddg.gg'))
|
||||
self.ui.downloaddir.setText(dldir)
|
||||
self.ui.adblock.setChecked(int(get.config('adblock', 1)))
|
||||
self.ui.hidetabs.setChecked(int(get.config('hidetabs', 1)))
|
||||
self.ui.reusetab.setChecked(int(get.config('reusetab', False)))
|
||||
self.ui.cachesize.setValue(int(get.config('cache', 100)))
|
||||
self.ui.darktheme.setChecked(int(get.config('darktheme', 0)))
|
||||
self.ui.nitter.setChecked(int(nitter_state))
|
||||
self.ui.nitterurl.setText(get.config('nitterurl', 'https://nitter.net'))
|
||||
self._general_set_nitterurl_state(nitter_state)
|
||||
self.ui.screpost.setChecked(int(get.config('scnoreposts', False)))
|
||||
|
||||
if isWindows:
|
||||
self.ui.setdefault.setDisabled(True)
|
||||
|
@ -142,10 +147,7 @@ class Preferences(object):
|
|||
self.ui.jsdebug.setChecked(get.config('jsdebug', False))
|
||||
self.ui.tracemalloc.setChecked(get.config('tracestart', False))
|
||||
self.ui.automd5.setChecked(get.config('automd5', False))
|
||||
|
||||
# this breaks for some reason, so keeping it disabled until I figure out what's going on
|
||||
self.ui.hostreset.setToolTip('Button broken. Just set the host to "127.0.0.1"')
|
||||
self.ui.hostreset.setDisabled(True)
|
||||
self.ui.mastocheck.setChecked(get.config('mastocheck', False))
|
||||
|
||||
## General tab signals
|
||||
self.ui.setdefault.clicked.connect(self._general_set_default)
|
||||
|
@ -157,7 +159,14 @@ class Preferences(object):
|
|||
self.ui.cachesize.editingFinished.connect(self._general_update_cachesize)
|
||||
self.ui.hidetabs.stateChanged.connect(lambda state: self._general_handle_checkbox(state, 'hidetabs'))
|
||||
self.ui.adblock.stateChanged.connect(lambda state: self._general_handle_checkbox(state, 'adblock'))
|
||||
self.ui.darktheme.stateChanged.connect(lambda state: self._general_handle_checkbox(state, 'darktheme'))
|
||||
self.ui.nitter.stateChanged.connect(lambda state: self._general_handle_checkbox(state, 'nitter'))
|
||||
self.ui.reusetab.stateChanged.connect(lambda state: self._general_handle_checkbox(state, 'reusetab'))
|
||||
self.ui.nitterurl.editingFinished.connect(self._general_update_nitter_url)
|
||||
self.ui.nitterreset.clicked.connect(self._general_reset_nitter_url)
|
||||
self.ui.screpost.stateChanged.connect(lambda state: self._general_handle_checkbox(state, 'scnoreposts'))
|
||||
|
||||
## Appearance tab signals
|
||||
#self.ui.theme.itemClicked.connect(self._appearance_theme_change)
|
||||
|
||||
## Search engine tab signals
|
||||
self.ui.snew.clicked.connect(lambda *args: self._search_button_handler('new'))
|
||||
|
@ -175,21 +184,28 @@ class Preferences(object):
|
|||
self.ui.domain.returnPressed.connect(lambda *args: self.ui.username.setFocus())
|
||||
self.ui.username.returnPressed.connect(lambda *args: self.ui.password.setFocus())
|
||||
self.ui.password.returnPressed.connect(self.mastodon_login)
|
||||
self.ui.accounts.itemSelectionChanged.connect(self.mastodon_row_selected)
|
||||
|
||||
## Advanced tab signals
|
||||
self.ui.mbushost.currentIndexChanged.connect(self._adv_mbushost_changed)
|
||||
self.ui.mbusport.editingFinished.connect(self._adv_mbusport_changed)
|
||||
self.ui.loglevel.currentIndexChanged.connect(lambda index: self._adv_changed('loglevel', index))
|
||||
self.ui.hostreset.clicked.connect(lambda *args: self._adv_reset('mhost'))
|
||||
self.ui.portreset.clicked.connect(lambda *args: self._adv_reset('mport'))
|
||||
self.ui.hostreset.clicked.connect(lambda *args: self._adv_mbushost_changed(int(default.mhost)))
|
||||
self.ui.portreset.clicked.connect(lambda *args: self._adv_mbusport_changed(default.mport))
|
||||
self.ui.logreset.clicked.connect(lambda *args: self._adv_reset('loglevel'))
|
||||
self.ui.jsdebug.stateChanged.connect(lambda state: self._adv_handle_checkbox('jsdebug', state))
|
||||
self.ui.tracemalloc.stateChanged.connect(lambda state: self._adv_handle_checkbox('tracestart', state))
|
||||
self.ui.automd5.stateChanged.connect(lambda state: self._adv_handle_checkbox('automd5', state))
|
||||
self.ui.mastocheck.stateChanged.connect(lambda state: self._adv_handle_checkbox('mastocheck', state))
|
||||
|
||||
## Populate tables
|
||||
self.mastodon_populate_table()
|
||||
self.populate_search_table()
|
||||
#self._appearance_populate_view()
|
||||
|
||||
# Remove the appearance tab until I can get it fixed
|
||||
self.ui.tabs.widget(1).deleteLater()
|
||||
self.ui.tabs.removeTab(1)
|
||||
|
||||
|
||||
### General Tab ###
|
||||
|
@ -293,10 +309,6 @@ class Preferences(object):
|
|||
self.window.profile.setHttpCacheMaximumSize(1024 * 1024 * value)
|
||||
|
||||
|
||||
def _general_homepage_reset(self, *args):
|
||||
self.ui.homepage.setText(self.window.homepage)
|
||||
|
||||
|
||||
def _general_update_homepage(self, *args):
|
||||
newurl = self.ui.homepage.text()
|
||||
|
||||
|
@ -314,21 +326,81 @@ class Preferences(object):
|
|||
if name == 'hidetabs':
|
||||
self.window.tabbar.setAutoHide(state.real)
|
||||
|
||||
if name == 'adblock':
|
||||
self.window.adblock = value
|
||||
|
||||
if name == 'darktheme':
|
||||
if name == 'nitter':
|
||||
value = boolean(value)
|
||||
self._general_set_nitterurl_state(value)
|
||||
|
||||
if value:
|
||||
ChangeTheme('dark')
|
||||
else:
|
||||
ChangeTheme()
|
||||
|
||||
def _general_set_nitterurl_state(self, value=None):
|
||||
if not value:
|
||||
value = get.config('nitter', False)
|
||||
|
||||
self.ui.nitterurl.setEnabled(value)
|
||||
self.ui.nitterreset.setEnabled(value)
|
||||
|
||||
|
||||
def _general_update_nitter_url(self):
|
||||
url = self.ui.nitterurl.text()
|
||||
|
||||
if not any(map(url.startswith, ['http://', 'https://'])):
|
||||
url = 'https://' + url
|
||||
self.ui.nitterurl.setText(url)
|
||||
|
||||
if not put.config('nitterurl', url):
|
||||
logging.error('Failed to update "nitterurl" config')
|
||||
|
||||
|
||||
def _general_reset_nitter_url(self):
|
||||
if not put.config('nitterurl', default.nitter):
|
||||
logging.error('Failed to update "nitterurl" config')
|
||||
return
|
||||
|
||||
self.ui.nitterurl.setText(default.nitter)
|
||||
|
||||
|
||||
### Appearance Tab ###
|
||||
def _appearance_populate_view(self):
|
||||
self.ui.theme.clear()
|
||||
size = QSize()
|
||||
size.setHeight(24)
|
||||
|
||||
default = QListWidgetItem('Default')
|
||||
default.setSizeHint(size)
|
||||
|
||||
if get.config('theme', 'Default') == 'Default':
|
||||
default.setIcon(Icon('okay', 16))
|
||||
|
||||
self.ui.theme.addItem(default)
|
||||
|
||||
for theme in get.theme():
|
||||
item = QListWidgetItem(theme.name)
|
||||
item.setForeground(theme.palette.text())
|
||||
item.setBackground(theme.palette.base())
|
||||
item.setSizeHint(size)
|
||||
|
||||
if get.config('theme') == theme.name:
|
||||
item.setIcon(Icon('okay', 16))
|
||||
|
||||
self.ui.theme.addItem(item)
|
||||
|
||||
|
||||
def _appearance_theme_change(self, item):
|
||||
listwidget = self.ui.theme
|
||||
theme = item.text()
|
||||
|
||||
if put.config('theme', theme):
|
||||
items = [listwidget.item(i) for i in range(listwidget.count())]
|
||||
|
||||
for item in items:
|
||||
if item.text() != theme:
|
||||
item.setIcon(QIcon())
|
||||
else:
|
||||
item.setIcon(Icon('okay', 16))
|
||||
|
||||
self.window.themes.ChangeTheme(theme)
|
||||
|
||||
|
||||
### Search Tab ###
|
||||
# todo: prefix functions with 'search'
|
||||
|
||||
def _search_button_handler(self, button):
|
||||
table = self.ui.sengines
|
||||
tablerow = table.currentRow()
|
||||
|
@ -368,7 +440,6 @@ class Preferences(object):
|
|||
return
|
||||
|
||||
table = self.ui.sengines
|
||||
cell = table.item(x, y)
|
||||
cells = [0, table.item(x, 1), table.item(x, 2), table.item(x, 3)]
|
||||
|
||||
data = {
|
||||
|
@ -429,6 +500,19 @@ class Preferences(object):
|
|||
logging.error('Invalid message type:', msgtype)
|
||||
|
||||
|
||||
def mastodon_row_selected(self):
|
||||
row = self.mastodon_selected_row_data()
|
||||
logging.debug(row)
|
||||
|
||||
if not row:
|
||||
self.ui.mdefault.setEnabled(False)
|
||||
self.ui.logout.setEnabled(False)
|
||||
|
||||
else:
|
||||
self.ui.mdefault.setEnabled(row['default'])
|
||||
self.ui.logout.setEnabled(True)
|
||||
|
||||
|
||||
def mastodon_selected_row_data(self):
|
||||
table = self.ui.accounts
|
||||
tablerow = table.currentRow() if table.currentRow() >= 0 else None
|
||||
|
@ -436,9 +520,10 @@ class Preferences(object):
|
|||
if tablerow == None:
|
||||
return
|
||||
|
||||
cells = [0, table.item(tablerow, 1), table.item(tablerow, 2), table.item(tablerow, 3)]
|
||||
cells = [table.item(tablerow, 0), table.item(tablerow, 1), table.item(tablerow, 2), table.item(tablerow, 3)]
|
||||
|
||||
data = {
|
||||
'default': cells[0].icon().isNull(),
|
||||
'displayname': cells[1].text() if cells[1] else None,
|
||||
'username': cells[2].text() if cells[2] else None,
|
||||
'domain': cells[3].text() if cells[3] else None
|
||||
|
@ -450,9 +535,13 @@ class Preferences(object):
|
|||
|
||||
def mastodon_populate_table(self):
|
||||
self.ui.accounts.setRowCount(0)
|
||||
accounts = get.mastoaccount()
|
||||
|
||||
for widget in [self.ui.mdefault, self.ui.logout]:
|
||||
widget.setEnabled(False)
|
||||
|
||||
#for row in db.get('mastodon', single=False):
|
||||
for row in get.mastoaccount():
|
||||
for row in accounts:
|
||||
self.mastodon_insert_row(row)
|
||||
|
||||
|
||||
|
@ -534,7 +623,7 @@ class Preferences(object):
|
|||
## Advanced tab
|
||||
def _adv_mbushost_changed(self, index):
|
||||
new = self.ui.mbushost.itemText(index)
|
||||
old = get.config('mhost')
|
||||
old = get.config('mhost', default.mhost)
|
||||
|
||||
if old != new:
|
||||
put.config('mhost', new)
|
||||
|
@ -546,8 +635,10 @@ class Preferences(object):
|
|||
self.window.server.restart()
|
||||
|
||||
|
||||
def _adv_mbusport_changed(self):
|
||||
value = self.ui.mbusport.value()
|
||||
def _adv_mbusport_changed(self, value=None):
|
||||
if not value:
|
||||
value = self.ui.mbusport.value()
|
||||
|
||||
put.config('mport', value)
|
||||
|
||||
self.window.server.restart()
|
||||
|
@ -574,15 +665,6 @@ class Preferences(object):
|
|||
|
||||
db.remove('config', row.id)
|
||||
|
||||
if field == 'mhost':
|
||||
self.ui.mbushost.setCurrentIndex(0)
|
||||
|
||||
if field == 'mport':
|
||||
self.ui.mbusport.setValue(8008)
|
||||
|
||||
if field in ['mhost', 'mport']:
|
||||
self.window.server.restart()
|
||||
|
||||
if field == 'loglevel':
|
||||
self.mbushost.setCurrentIndex(3)
|
||||
logging.setConfig({'level': 'INFO'})
|
||||
|
|
139
qtweb/themes.py
139
qtweb/themes.py
|
@ -1,111 +1,74 @@
|
|||
from .Lib.IzzyLib import logging
|
||||
|
||||
from . import isWindows
|
||||
from .database import get, put
|
||||
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtWidgets import QStyleFactory
|
||||
|
||||
|
||||
color_themes = {}
|
||||
default_style = None
|
||||
current_theme = None
|
||||
app = None
|
||||
class ColorTheme(object):
|
||||
def __init__(self, window):
|
||||
self.app = window.app
|
||||
self.window = window
|
||||
self.default_style = self.app.style().objectName().lower()
|
||||
self.default_palette = self.app.style().standardPalette()
|
||||
self.appcolor = self.app.palette()
|
||||
self.colors = [
|
||||
'Window', 'WindowText', 'Base', 'AlternateBase', 'ToolTipBase', 'ToolTipText',
|
||||
'Button', 'ButtonText', 'Text', 'Highlight', 'HighlightedText', 'Link',
|
||||
'Light', 'Midlight', 'Dark', 'Mid', 'Shadow', 'LinkVisited', 'BrightText'
|
||||
]
|
||||
self.colors.sort()
|
||||
|
||||
logging.verbose('Default style:', self.default_style)
|
||||
logging.verbose('Available styles:', ', '.join(QStyleFactory.keys()))
|
||||
|
||||
|
||||
dark = {
|
||||
'AlternateBase': QColor(53, 53, 53),
|
||||
'Base': QColor(25, 25, 25),
|
||||
'Button': QColor(53, 53, 53),
|
||||
'ButtonText': Qt.white,
|
||||
'BrightText': Qt.red,
|
||||
'Highlight': QColor(42, 130, 218),
|
||||
'HighlightedText': Qt.black,
|
||||
'Link': QColor(42, 130, 218),
|
||||
'Text': Qt.white,
|
||||
'ToolTipBase': Qt.black,
|
||||
'ToolTipText': Qt.white,
|
||||
'Window': QColor(53, 53, 53),
|
||||
'WindowText': Qt.white,
|
||||
}
|
||||
def ChangeTheme(self, theme=None):
|
||||
theme = 'Default' if not theme else theme
|
||||
|
||||
if theme == 'Default':
|
||||
palette = self.default_palette
|
||||
|
||||
def AddTheme(name, colors):
|
||||
name = name.title()
|
||||
theme = QPalette()
|
||||
|
||||
for colname, color in colors.items():
|
||||
theme.setColor(getattr(QPalette, colname), QColor(color) if type(color) == str else color)
|
||||
|
||||
color_themes[name] = theme
|
||||
|
||||
|
||||
def RemoveTheme(name):
|
||||
name = name.title()
|
||||
if not color_themes.get(name):
|
||||
logging.error('Not a valid theme:', name)
|
||||
return
|
||||
|
||||
del color_themes[name]
|
||||
|
||||
|
||||
def GetTheme(name=None):
|
||||
if not name:
|
||||
return color_themes
|
||||
|
||||
name = name.title()
|
||||
theme = color_themes.get(name)
|
||||
|
||||
if not theme:
|
||||
logging.error('Not a valid theme:', name)
|
||||
return
|
||||
|
||||
return theme
|
||||
|
||||
|
||||
def ChangeTheme(theme=None):
|
||||
global current_theme
|
||||
|
||||
theme = 'Default' if not theme else theme.title()
|
||||
newtheme = color_themes.get(theme)
|
||||
|
||||
if not newtheme:
|
||||
logging.error('Not a valid theme:', theme)
|
||||
return
|
||||
|
||||
if isWindows:
|
||||
if theme != 'Default':
|
||||
app.setStyle('fusion')
|
||||
else:
|
||||
app.setStyle(default_style)
|
||||
row = get.theme(theme)
|
||||
|
||||
logging.verbose('Changing color theme to', theme)
|
||||
if not row:
|
||||
logging.error('Not a valid theme:', theme)
|
||||
return
|
||||
|
||||
current_theme = theme
|
||||
app.setPalette(newtheme)
|
||||
palette = row.palette
|
||||
|
||||
logging.verbose('Changing color theme to', theme)
|
||||
put.config('theme', theme)
|
||||
self.app.setPalette(palette)
|
||||
|
||||
if isWindows:
|
||||
if theme != 'Default':
|
||||
self.app.setStyle('fusion')
|
||||
|
||||
else:
|
||||
self.app.setStyle(self.default_style)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def SetupThemes(appclass):
|
||||
global default_style
|
||||
global app
|
||||
def ColorToPalette(self, data):
|
||||
palette = self.app.style().standardPalette()
|
||||
|
||||
app = appclass
|
||||
default_style = app.style().objectName().lower()
|
||||
appcolor = app.palette()
|
||||
for name, color in data.items():
|
||||
if name in self.colors and color != None:
|
||||
palette.setColor(getattr(QPalette, name), QColor(color))
|
||||
|
||||
colors = {}
|
||||
defcolors = [
|
||||
'Window', 'WindowText', 'Base', 'AlternateBase', 'ToolTipBase', 'ToolTipText', 'Button', 'ButtonText',
|
||||
'BrightText', 'Light', 'Midlight', 'Dark', 'Mid', 'Shadow', 'Highlight', 'HighlightedText', 'Link', 'LinkVisited'
|
||||
]
|
||||
return palette
|
||||
|
||||
for color in defcolors:
|
||||
lowercolor = color[0].lower() + color[1:]
|
||||
colors[color] = getattr(appcolor, lowercolor)().color()
|
||||
|
||||
AddTheme('Default', colors)
|
||||
AddTheme('dark', dark)
|
||||
def PaletteToColor(self, palette):
|
||||
data = {}
|
||||
|
||||
logging.verbose('Default style:', default_style)
|
||||
logging.verbose('Available styles:', ', '.join(QStyleFactory.keys()))
|
||||
logging.verbose('Available themes:', ', '.join(color_themes.keys()))
|
||||
for color in self.colors:
|
||||
data[color] = getattr(palette, color[0].lower() + ''.join(color[1:]))().color().name()
|
||||
|
||||
return data
|
||||
|
|
|
@ -1,49 +1,71 @@
|
|||
import sys
|
||||
|
||||
from . import debstable
|
||||
from .config import var
|
||||
from .database import db, put
|
||||
|
||||
from .Lib.IzzyLib import logging
|
||||
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtWebEngineCore import *
|
||||
|
||||
|
||||
def RegisterScheme(name):
|
||||
scheme = QWebEngineUrlScheme(name.encode())
|
||||
scheme.setFlags(QWebEngineUrlScheme.SecureScheme)
|
||||
QWebEngineUrlScheme.registerScheme(scheme)
|
||||
scheme = QWebEngineUrlScheme(name.encode())
|
||||
scheme.setFlags(
|
||||
#QWebEngineUrlScheme.LocalScheme |
|
||||
QWebEngineUrlScheme.LocalAccessAllowed |
|
||||
QWebEngineUrlScheme.ViewSourceAllowed
|
||||
)
|
||||
|
||||
QWebEngineUrlScheme.registerScheme(scheme)
|
||||
|
||||
|
||||
class LocalHandler(QWebEngineUrlSchemeHandler):
|
||||
def __init__(self, webview, window):
|
||||
super().__init__(window)
|
||||
self.webview = webview
|
||||
def __init__(self, parent):
|
||||
self.window = parent
|
||||
|
||||
def requestStarted(self, job):
|
||||
url = job.requestUrl()
|
||||
host = url.host()
|
||||
if not debstable:
|
||||
scheme = QWebEngineUrlScheme.schemeByName(var.local.encode())
|
||||
|
||||
if scheme.name() == b'':
|
||||
logging.critical(f'Failed to register scheme: {var.local}. Exiting...')
|
||||
parent.close()
|
||||
|
||||
super().__init__(parent.profile)
|
||||
parent.profile.installUrlSchemeHandler(var.local.encode(), self)
|
||||
|
||||
|
||||
def _check_initiator(self, request):
|
||||
initiator = request.initiator()
|
||||
requrl = request.requestUrl()
|
||||
|
||||
if requrl.scheme() != var.local:
|
||||
logging.warning(f'Blocking malicious request from {initiator.toDisplayString()} to {request_url.toDisplayString()}')
|
||||
request.fail(QWebEngineUrlRequestJob.RequestDenied)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def requestStarted(self, request):
|
||||
url = request.requestUrl()
|
||||
path = url.path()
|
||||
|
||||
job.fail(QWebEngineUrlRequestJob.UrlNotFound)
|
||||
if not self._check_initiator(request):
|
||||
return
|
||||
|
||||
if url.host() == 'home':
|
||||
mimetype = 'text/html'
|
||||
data = b'<html><head><title>MERP!</title><body>UvU</body></html>'
|
||||
|
||||
blockedDomain = [
|
||||
'doubleclick.net',
|
||||
'rubiconproject.com',
|
||||
'outbrain.com',
|
||||
'googletagservices.com',
|
||||
'amazon-adsystem.com',
|
||||
'optimizely.com',
|
||||
'adswizz.com'
|
||||
]
|
||||
else:
|
||||
mimetype = 'text/html'
|
||||
data = '<html><head><title>QtWeb</title><body>heck</body></html>'
|
||||
|
||||
blockedURL = {
|
||||
'youtube.com': [
|
||||
'/api/stats/ads',
|
||||
'/pagead/adview',
|
||||
'/pagead/lvz'
|
||||
'/get_midroll/info'
|
||||
],
|
||||
'soundcloud.com': [
|
||||
'/audio-ads'
|
||||
],
|
||||
'facebook.com': [
|
||||
'/tr']
|
||||
}
|
||||
buf = QBuffer(parent=self)
|
||||
buf.open(QIODevice.WriteOnly)
|
||||
buf.write(data)
|
||||
buf.seek(0)
|
||||
buf.close()
|
||||
request.reply(mimetype.encode('ascii'), buf)
|
||||
|
|
220
qtweb/webview.py
220
qtweb/webview.py
|
@ -5,12 +5,13 @@ import validators
|
|||
|
||||
from .Lib.IzzyLib import logging
|
||||
from .Lib.IzzyLib.misc import boolean
|
||||
from .Lib.IzzyLib.cache import LRUCache
|
||||
|
||||
from . import debstable, dialogs
|
||||
from .config import var
|
||||
from . import debstable, dialogs, debstable
|
||||
from .config import var, default
|
||||
from .database import db, get, put
|
||||
from .mastodon import Mastodon
|
||||
from .functions import Menu, Icon
|
||||
from .functions import Menu, Icon, httpclient
|
||||
from .webviewjs import JsFuncs
|
||||
|
||||
from PyQt5.QtCore import *
|
||||
|
@ -40,6 +41,7 @@ class WebEngineView(QWebEngineView):
|
|||
super().__init__()
|
||||
|
||||
self.window = window
|
||||
self.jscache = LRUCache(64)
|
||||
self.webview = True
|
||||
self.tabs = window.ui.tabs
|
||||
self.webpage = WebEnginePage(self.window.profile, self)
|
||||
|
@ -54,15 +56,17 @@ class WebEngineView(QWebEngineView):
|
|||
|
||||
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
self.customContextMenuRequested.connect(self._web_context_menu)
|
||||
#self.loadStarted.connect(lambda *args: setattr(self, 'loading', True))
|
||||
self.loadProgress.connect(self._progress_loading)
|
||||
#self.loadStarted.connect(self._started_loading)
|
||||
self.loadFinished.connect(self._finished_loading)
|
||||
|
||||
self.webpage.titleChanged.connect(self._set_tab_text)
|
||||
self.webpage.iconChanged.connect(self._set_tab_icon)
|
||||
self.webpage.urlChanged.connect(self._set_tab_url)
|
||||
self.webpage.linkHovered.connect(self._link_hover)
|
||||
self.webpage.fullScreenRequested.connect(lambda *args: self._permission_request('fullscreen', *args))
|
||||
#self.webpage.fullScreenRequested.connect(lambda *args: self._permission_request('fullscreen', *args))
|
||||
self.webpage.featurePermissionRequested.connect(self._feature_request)
|
||||
self.webpage.authenticationRequired.connect(self._handle_auth)
|
||||
|
||||
self.webaction_state = {
|
||||
'previous': False,
|
||||
|
@ -79,15 +83,68 @@ class WebEngineView(QWebEngineView):
|
|||
self.JsAction = JsFuncs(self)
|
||||
|
||||
if url != 'newtab':
|
||||
self.LoadUrl(url if url else get.config('homepage', 'https://ddg.gg'))
|
||||
self.LoadUrl(url if url else get.config('homepage', default.homepage))
|
||||
|
||||
|
||||
def _progress_loading(self, progress):
|
||||
current_index = self.window.ui.tabs.currentIndex()
|
||||
tab_index = self.window.ui.tabs.indexOf(self)
|
||||
loading = progress != 100
|
||||
percent = progress / 100
|
||||
|
||||
self.webaction_state['stop'] = loading
|
||||
self.webaction_state['reload'] = not loading
|
||||
|
||||
if current_index == tab_index:
|
||||
#if loading:
|
||||
#self.window.ui.url.setStyleSheet('background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop: 0 #1bb77b, stop: ' + str(percent) + ' #1bb77b, stop: ' + str(percent+ 0.001) + ' rgba(0, 0, 0, 0), stop: 1 white)')
|
||||
#else:
|
||||
#self.window.ui.url.setStyleSheet(None)
|
||||
|
||||
self.window._update_webaction_buttons('stop', self.webaction_state['stop'])
|
||||
self.window._update_webaction_buttons('reload', self.webaction_state['reload'])
|
||||
|
||||
|
||||
# There's a lot of code duplication here. Gonna fix that later
|
||||
def _finished_loading(self, arg):
|
||||
jsfile = Path(var.scriptpath, 'web', 'js', self.url().host() + '.js')
|
||||
host = self.url().host()
|
||||
path = self.url().path()
|
||||
jsfile = Path(var.scriptpath, 'scripts', self.url().host() + '.js')
|
||||
userjsfile = Path(var.datapath, 'UserScripts', self.url().host() + '.js')
|
||||
jscache = self.jscache.fetch(host)
|
||||
userjscache = self.jscache.fetch(host + '.User')
|
||||
|
||||
if jsfile.exists():
|
||||
with jsfile.open('r') as fd:
|
||||
self.webpage.runJavaScript(fd.read())
|
||||
if jsfile.exists() and jsfile.is_file():
|
||||
if jscache:
|
||||
logging.verbose(f'Loading JS from cache for {host}: {jsfile}')
|
||||
data = jscache
|
||||
|
||||
else:
|
||||
logging.verbose(f'Loading JS from file for {host}: {jsfile}')
|
||||
with jsfile.open('r') as fd:
|
||||
data = fd.read()
|
||||
self.jscache.store(host, data)
|
||||
|
||||
self.webpage.runJavaScript(data)
|
||||
|
||||
|
||||
if userjsfile.exists() and userjsfile.is_file():
|
||||
if userjscache:
|
||||
logging.verbose(f'Loading user JS from cache for {host:} {userjsfile}')
|
||||
userdata = userjscache
|
||||
|
||||
logging.verbose(f'Loading user JS from file for {host}: {userjsfile}')
|
||||
with userjsfile.open('r') as fd:
|
||||
userdata = fd.read()
|
||||
self.jscache.store(host + '.User', userdata)
|
||||
|
||||
self.webpage.runJavaScript(userdata)
|
||||
|
||||
if host == 'soundcloud.com' and path.startswith('/stream') and get.config('scnoreposts', False):
|
||||
self.webpage.runJavaScript('window.addEventListener("DOMNodeInserted", norepost, false);')
|
||||
|
||||
if get.config('reusetab', False):
|
||||
self.webpage.runJavaScript('for (let link of document.getElementsByTagName("a")) {if (link.target === "_blank") link.removeAttribute("target")}')
|
||||
|
||||
|
||||
def _set_tab_text(self, title):
|
||||
|
@ -121,6 +178,9 @@ class WebEngineView(QWebEngineView):
|
|||
action = recv_action.text().lower()
|
||||
state = recv_action.isEnabled()
|
||||
|
||||
if action in ['stop', 'reload']:
|
||||
return
|
||||
|
||||
self.webaction_state[action] = state
|
||||
|
||||
if current_index == tab_index:
|
||||
|
@ -168,11 +228,26 @@ class WebEngineView(QWebEngineView):
|
|||
self.Fullscreen(request.toggleOn())
|
||||
|
||||
|
||||
def _handle_auth(self, location, authenticator):
|
||||
url = location.toString()
|
||||
login = dialogs.HttpAuth(location, authenticator, self)
|
||||
login.exec_()
|
||||
|
||||
if login.result:
|
||||
logging.verbose('Authenticated page:', url)
|
||||
|
||||
else:
|
||||
logging.verbose('Canceled authentication for page:', url)
|
||||
self.stop()
|
||||
|
||||
if self.window.ui.tabs.currentWidget() == self:
|
||||
self.window.ui.url.setText(url)
|
||||
|
||||
|
||||
def _web_context_menu(self, point):
|
||||
cursor = QCursor().pos() #point puts the menu in the wrong location for some reason
|
||||
data = self.webpage.contextMenuData()
|
||||
clipboard = self.window.clipboard
|
||||
mimedata = clipboard.mimeData()
|
||||
currenturl = self.url()
|
||||
spliturl = currenturl.path().split('/')
|
||||
selected = data.selectedText()
|
||||
|
@ -188,17 +263,10 @@ class WebEngineView(QWebEngineView):
|
|||
acctcount = db.count('mastodon') > 0
|
||||
|
||||
mediaurl = data.mediaUrl().toString()
|
||||
menu = Menu('heck', self)
|
||||
menu = Menu(self, 'heck')
|
||||
addItem = lambda label, name, data=None: menu.AddAction(label, lambda : self._menu_actions(name, data))
|
||||
addMastoItem = lambda label, name, data=None: menu.AddAction(label, lambda : self._mastodon_action(name, data))
|
||||
|
||||
if mediaurl != '':
|
||||
addItem('Open Media in New Tab', 'newtab', mediaurl)
|
||||
addItem('Open Media in New Tab and Switch', 'newtabswitch', mediaurl)
|
||||
menu.AddSeparator()
|
||||
addItem('Download Media', 'download', mediaurl)
|
||||
addItem('Copy Media URL', 'copy', mediaurl)
|
||||
|
||||
## Not sure if I wanna enable this
|
||||
#if acctcount and urlismasto and urlispost:
|
||||
#addItem('Reply to Post', 'reply', currenturl.toString())
|
||||
|
@ -213,17 +281,7 @@ class WebEngineView(QWebEngineView):
|
|||
addItem('Open Link in New Tab', 'newtab', linkurl)
|
||||
addItem('Open Link in New Tab and Switch', 'newtabswitch', linkurl)
|
||||
menu.AddSeparator()
|
||||
addItem('Download Link', 'download', linkurl)
|
||||
menu.AddSeparator()
|
||||
|
||||
if acctcount and linkispost and linkismasto:
|
||||
addMastoItem('Reply to Linked Post', 'reply', linkurl)
|
||||
addMastoItem('Favorite Linked Post', 'favourite', linkurl)
|
||||
addMastoItem('Boost Linked Post', 'reblog', linkurl)
|
||||
addMastoItem('Bookmark Linked Post', 'bookmark', linkurl)
|
||||
|
||||
menu.AddSeparator()
|
||||
addItem('Copy Link URL', 'copyurl')
|
||||
addItem('Copy Link Location', 'copyurl')
|
||||
addItem('Copy Link Text', 'copy', linktext)
|
||||
|
||||
if selected:
|
||||
|
@ -244,9 +302,27 @@ class WebEngineView(QWebEngineView):
|
|||
if data.CanRedo:
|
||||
addItem('Redo', 'Redo')
|
||||
|
||||
if linkurl != '':
|
||||
addItem('Download Link', 'download', linkurl)
|
||||
|
||||
if acctcount and linkispost and linkismasto:
|
||||
menu.AddSeparator()
|
||||
addMastoItem('Reply to Linked Post', 'reply', linkurl)
|
||||
addMastoItem('Favorite Linked Post', 'favourite', linkurl)
|
||||
addMastoItem('Boost Linked Post', 'reblog', linkurl)
|
||||
addMastoItem('Bookmark Linked Post', 'bookmark', linkurl)
|
||||
|
||||
if menu.MoreThan(0):
|
||||
menu.AddSeparator()
|
||||
|
||||
if mediaurl != '':
|
||||
addItem('Open Media in New Tab', 'newtab', mediaurl)
|
||||
addItem('Open Media in New Tab and Switch', 'newtabswitch', mediaurl)
|
||||
menu.AddSeparator()
|
||||
addItem('Download Media', 'download', mediaurl)
|
||||
addItem('Copy Media Location', 'copy', mediaurl)
|
||||
menu.AddSeparator()
|
||||
|
||||
addItem('Inspect Page', 'inspect_page')
|
||||
addItem('Inspect Element', 'inspect')
|
||||
menu.AddSeparator()
|
||||
|
@ -390,10 +466,12 @@ class WebEngineView(QWebEngineView):
|
|||
twitter_paths = any(map(parsed.path.startswith, ['/settings', '/home', '/login', '/logout', '/explore', '/sessions', '/account']))
|
||||
twitter_files = any(map(parsed.path.endswith, ['.js', '.jpeg', '.jpg', '.png', '.css']))
|
||||
|
||||
if parsed.netloc == 'twitter.com' and get.config('twiredir', True) and parsed.path != '/' and not twitter_paths and not twitter_files:
|
||||
newurl = f'https://nitter.net{parsed.path}'
|
||||
if parsed.netloc == 'twitter.com' and get.config('nitter', False) and parsed.path != '/' and not twitter_paths and not twitter_files:
|
||||
nitterurl = get.config('nitterurl', default.nitter)
|
||||
newurl = nitterurl + parsed.path
|
||||
|
||||
self.webpage.setUrl(QUrl(newurl))
|
||||
self.setFocus()
|
||||
|
||||
|
||||
class SearchBar(QFrame):
|
||||
|
@ -403,7 +481,7 @@ class SearchBar(QFrame):
|
|||
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.setContentsMargins(0, 0, 0, 2)
|
||||
layout.setContentsMargins(0, 6, 0, 0)
|
||||
layout.setSpacing(4)
|
||||
#layout.setSizeConstraint(QLayout.SetFixedSize)
|
||||
self.setLayout(layout)
|
||||
|
@ -418,10 +496,6 @@ class SearchBar(QFrame):
|
|||
close.setIcon(Icon('close'))
|
||||
|
||||
for widget in [previous, next, self.search, self.sensitive, reset, close]:
|
||||
#if widget == self.search:
|
||||
#widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
|
||||
#else:
|
||||
#widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
|
||||
self.layout().addWidget(widget)
|
||||
|
||||
self.search.installEventFilter(FindEsc(self))
|
||||
|
@ -434,17 +508,18 @@ class SearchBar(QFrame):
|
|||
close.clicked.connect(lambda *args: self.Search('toggle'))
|
||||
|
||||
|
||||
def Search(self, action=None):
|
||||
def Search(self, action=None, text=None):
|
||||
if text:
|
||||
self.search.setText(text)
|
||||
text = self.search.text()
|
||||
webview = self.webview
|
||||
selected = webview.selectedText()
|
||||
selected = self.webview.selectedText()
|
||||
sensitive = self.sensitive.isChecked()
|
||||
|
||||
if action == 'previous':
|
||||
webview.Search(text, reverse=True, sensitive=sensitive)
|
||||
self.webview.Search(text, reverse=True, sensitive=sensitive)
|
||||
|
||||
elif action == 'reset':
|
||||
webview.Search()
|
||||
self.webview.Search()
|
||||
self.sensitive.setChecked(False)
|
||||
self.search.setText('')
|
||||
|
||||
|
@ -461,12 +536,12 @@ class SearchBar(QFrame):
|
|||
self.Search()
|
||||
|
||||
else:
|
||||
## Reset the search and focus the webview
|
||||
## Reset the search and focus the window
|
||||
self.Search('reset')
|
||||
webview.setFocus()
|
||||
self.webview.setFocus()
|
||||
|
||||
else:
|
||||
webview.Search(text, sensitive=sensitive)
|
||||
self.webview.Search(text, sensitive=sensitive)
|
||||
|
||||
|
||||
class FindEsc(QObject):
|
||||
|
@ -512,12 +587,14 @@ class WebEnginePage(QWebEnginePage):
|
|||
|
||||
def createWindow(self, wintype):
|
||||
options = {'nexttab': True}
|
||||
#wintypes = [
|
||||
#QWebEnginePage.WebBrowserTab,
|
||||
#QWebEnginePage.WebBrowserWindow,
|
||||
#QWebEnginePage.WebBrowserBackgroundTab,
|
||||
#QWebEnginePage.WebDialog
|
||||
#]
|
||||
wintypes = {
|
||||
QWebEnginePage.WebBrowserTab: 'new tab',
|
||||
QWebEnginePage.WebBrowserWindow: 'new window',
|
||||
QWebEnginePage.WebBrowserBackgroundTab: 'new background tab',
|
||||
QWebEnginePage.WebDialog: 'new dialog'
|
||||
}
|
||||
|
||||
typename = wintypes.get(wintype, f'Invalid window type: {type(wintype)}')
|
||||
|
||||
if wintype != QWebEnginePage.WebDialog:
|
||||
options['switch'] = True
|
||||
|
@ -525,9 +602,30 @@ class WebEnginePage(QWebEnginePage):
|
|||
return self.webview.window.NewWebTab('newtab' ,**options).webpage
|
||||
|
||||
|
||||
def triggerAction(self, action, checked=False):
|
||||
if action == QWebEnginePage.OpenLinkInNewWindow:
|
||||
self.createWindow(QWebEnginePage.WebBrowserWindow)
|
||||
|
||||
return super(WebEnginePage, self).triggerAction(action, checked)
|
||||
|
||||
|
||||
def acceptNavigationRequest(self, url, Type, isMainFrame):
|
||||
parsed = urlparse(url.toString())
|
||||
|
||||
types = {
|
||||
QWebEnginePage.NavigationTypeLinkClicked: 'link clicked',
|
||||
QWebEnginePage.NavigationTypeTyped: 'loaded url',
|
||||
QWebEnginePage.NavigationTypeFormSubmitted: 'form submission',
|
||||
QWebEnginePage.NavigationTypeBackForward: 'back/forward action',
|
||||
QWebEnginePage.NavigationTypeReload: 'reloaded',
|
||||
QWebEnginePage.NavigationTypeOther: 'other type'
|
||||
}
|
||||
|
||||
if not debstable:
|
||||
types[QWebEnginePage.NavigationTypeRedirect] = 'redirected'
|
||||
|
||||
typename = types.get(Type, 'Invalid nav type')
|
||||
|
||||
return QWebEnginePage.acceptNavigationRequest(self, url, Type, isMainFrame)
|
||||
|
||||
|
||||
|
@ -537,6 +635,7 @@ class DevPage(QMainWindow):
|
|||
self.profile = profile
|
||||
self.window = parent
|
||||
self.view = None
|
||||
self.page = None
|
||||
#self.setGeometry(100, 100, 800, 600)
|
||||
self.resize(800, 600)
|
||||
|
||||
|
@ -547,26 +646,25 @@ class DevPage(QMainWindow):
|
|||
self.setCentralWidget(self.view)
|
||||
self.setWindowTitle(f'QtWeb Inspector: {url}')
|
||||
self.show()
|
||||
self.activateWindow()
|
||||
|
||||
return self.page
|
||||
|
||||
|
||||
def closeEvent(self, event):
|
||||
def closeEvent(self, event=None):
|
||||
logging.debug('closing dev tools')
|
||||
#self.view.deleteLater()
|
||||
#self.page.deleteLater()
|
||||
#del self.view
|
||||
#del self.page
|
||||
event.accept()
|
||||
self.view.deleteLater()
|
||||
self.page.deleteLater()
|
||||
self.view = None
|
||||
self.page = None
|
||||
|
||||
|
||||
def heck(self):
|
||||
print('HECK!')
|
||||
if event:
|
||||
event.accept()
|
||||
|
||||
|
||||
class DevWebEnginePage(QWebEnginePage):
|
||||
def __init__(self, profile, parent):
|
||||
super().__init__(profile)
|
||||
super().__init__(profile, parent)
|
||||
self.window = parent
|
||||
|
||||
|
||||
|
|
|
@ -4,9 +4,6 @@ from .config import var
|
|||
|
||||
from .Lib.IzzyLib import logging
|
||||
|
||||
from PyQt5.QtWebChannel import QWebChannel
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
|
||||
|
||||
|
||||
class JsFuncs(object):
|
||||
def __init__(self, webview):
|
||||
|
|
|
@ -4,3 +4,5 @@ publicsuffixlist
|
|||
asyncqt
|
||||
urllib3
|
||||
dbutils
|
||||
jinja2
|
||||
hamlpy3
|
||||
|
|
Reference in a new issue