公开/公告号CN112541138A
专利类型发明专利
公开/公告日2021-03-23
原文格式PDF
申请/专利权人 深圳市哈哈丫丫互联网有限公司;
申请/专利号CN202011590236.7
发明设计人 芮爱平;
申请日2020-12-29
分类号G06F16/955(20190101);
代理机构
代理人
地址 518109 广东省深圳市龙华区大浪街道高峰社区和平路龙军花园A1A2栋一单元1504室
入库时间 2023-06-19 10:21:15
技术领域
浏览器书签新技术。
背景技术
经过26年的发展,传统浏览器形成了一些固定的风格,其中有些并不实用,比如:“书签”被分成书签栏书签、其他书签和文件夹书签(图1),非常繁琐;而且其他书签和文件夹书签是以三级菜单(图2)提供的,影响了使用效率。书签栏书签虽然点击方便了,但界面复杂性抵消了便捷性。另外,谷歌浏览器和其他常见浏览器的收藏书签窗口以三级菜单提供(图3),用户体验差。鼠标右击谷歌浏览器书签的菜单(图4)包含12种功能,除“删除”功能外都不常用,给用户造成困扰。
发明内容
本发明是:采用“单一化书签”替代“书签栏书签、其他书签和文件夹书签”,回归本原,体现“简单就是美”的简约理念。采用网页空白处鼠标右击一级菜单收藏书签(图5)和使用我的书签(图6),改善用户体验。自动把光标定位在书签窗口的第一条(图7),增加灵敏度并节省操作时间;新添加和刚使用的书签总放在最前面,方便重复使用;控制书签总数为108±3个,每列显示36±1个书签,最多分3列显示(图8),体现书签数量够用且界面简洁的原则,hahayaya极速简约防盗Linux全屏浏览器之“我的书签”窗口如图7居中置顶显示,保护用户颈椎。右击任何书签只有“删除”功能(图9),用户可选择删除。
附图说明
图 1.谷歌浏览器的书签栏和其他书签分离的界面示意图
图 2.谷歌浏览器的“其他书签”功能的三级菜单窗口
图 3.谷歌浏览器的“收藏书签”功能的三级菜单窗口
图 4.谷歌浏览器的“其他书签”窗口鼠标右击菜单窗口有12项功能示意图
图 5.hahayaya极速简约防盗Linux全屏浏览器网页空白处右击菜单的“收藏书签”功能
图 6.hahayaya极速简约防盗Linux全屏浏览器网页空白处右击菜单的“我的书签”功能
图 7.hahayaya极速简约防盗Linux全屏浏览器“我的书签”功能的单列居中显示窗口
图 8.hahayaya极速简约防盗Linux全屏浏览器“我的书签”功能的三列居中显示窗口
图 9.hahayaya极速简约防盗Linux全屏浏览器“书签窗口”右击书签的“删除”功能。
具体实施方式
采用Linux系统的Python 3.7版语言、PyQt5 和 PyQtWebEingine 开发包实现“极速简约防盗Linux全屏浏览器”,开发平台是 PyCharm community 2019.3版。开发成功的hahayaya极速简约防盗全屏浏览器中,实现了发明内容所述的“收藏书签和我的书签”软件功能。注释行以#开头,/ 是折行连接符,简单易懂的代码不加注释,实现“收藏书签和我的书签”软件功能的重要代码用粗体显示,代码如下:
import sys,json,os,datetime,warnings,base64
from subprocess import Popen
from PyQt5.QtCore import QUrl, Qt, QCoreApplication, pyqtSignal,QDir, QFileInfo,/
/ QStandardPaths
from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit,QToolBar, QTabWidget, /
/ QWidget, QHBoxLayout,QDialog, QPushButton, QProgressBar, QMenu,QLabel, /
/ QMessageBox,QAction,QTreeView,QFileDialog
from PyQt5.QtGui import QIcon,QDesktopServices,QCursor,QStandardItemModel,QStandardItem
from PyQt5.QtWebEngineWidgets import QWebEngineView,QWebEngineSettings, /
/ QWebEngineDownloadItem, QWebEnginePage
from pynput.keyboard import Controller,Key
# 导入第三方开发包
download_item_ls = []
# 储存下载任务数组变量
webview_group = []
# 储存网页实例数组变量
webview_parent_group = []
# 储存网页父实例数组变量
class myQMenu(QMenu):
# 重写QMenu菜单类
def __init__(self, parent=None):
super(myQMenu, self).__init__(parent)
def leaveEvent(self, QEvent):
# 鼠标离开菜单,就关闭菜单
self.close()
_url_role = Qt.UserRole + 1
# 书签角色变量
_default_bookmarks = [
['我的书签'],
['http://www.hahayaya.com/', 'hahayaya', 'bookmarks/hhyy.png'],
['https://tv.cctv.com/live/cctv15_spm=C28340.PO8MkQf6Euyz.S91117.48',/
/ 'CCTV音乐频道', 'bookmarks/163_music.jpg'],
['https://www.youku.com/', '优酷', 'bookmarks/youku.jpg'],
['https://v.qq.com/', '腾讯视频', 'bookmarks/tencent.jpg'],
['浏览足迹'],
]
# 默认书签
class BookmarkWidget(myQMenu):
# 重写书签类, 继承myQMenu类
open_bookmark = pyqtSignal(QUrl)
# 设定信号变量 open_bookmark
changed = pyqtSignal()
# 设定信号变量 changed
def __init__(self):
# 初始化方法
super(BookmarkWidget, self).__init__()
self._model = self._create_model(self,self._read_bookmarks())
# 调用_read_bookmarks方法读取书签文件内容或默认书签变量创建书签模型变量
self._model.rowsInserted.connect(self._changed)
self._model.rowsRemoved.connect(self._changed)
self._model.dataChanged.connect(self._changed)
self._model.item(1, 0).removeRows(0,self._model.item(1, 0).rowCount())
# 把浏览足迹的变量self._model.item(1, 0)清空, self._model.item(0, 0)保存的是书签
def _changed(self):
# 书签变量有变化触发本方法
self.changed.emit()
def _action_activated(self, index):
# 书签被点击后触发本方法
self.open_bookmark.emit(self.sender().data())
def _config_dir(self):
# 创建隐藏目录.config保存书签文件和浏览器的缓存图片
return '{}/Rui_Browser'.format(QStandardPaths.writableLocation( /
/ QStandardPaths.ConfigLocation))
def _create_folder_item(self, title):
# 按书签的单项内容名称(如:'我的书签'或'浏览足迹')创建文件夹
result = QStandardItem(title)
result.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
return result
def _create_item(self, url, title, icon):
# 创建书签数据项方法
result = QStandardItem(title)
result.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
result.setData(url, _url_role)
if icon is not None: result.setIcon(icon)
return result
def _create_model(self, parent, serialized_bookmarks):
# 根据读取的书签变量创建书签数据模型的方法
result = QStandardItemModel(0, 1, parent)
last_folder_item = None
for entry in serialized_bookmarks:
if len(entry) == 1:
# 如书签数据只有一项,则创建目录
last_folder_item = self._create_folder_item(entry[0])
result.appendRow(last_folder_item)
else:
# 如书签数据有多项,则创建数据变量,并添加到数据模型
url = QUrl.fromUserInput(entry[0])
title = entry[1]
if len(entry) > 2 and entry[2]:icon = QIcon(entry[2])
else:icon = None
last_folder_item.appendRow(self._create_item(url,title, icon))
return result
def _serialize_model(self, model, directory):
# 书签数据模型串行化处理的方法
result = []
folder_count = model.rowCount()
for f in range(0, folder_count):
folder_item = model.item(f)
result.append([folder_item.text()])
item_count = folder_item.rowCount()
for i in range(0, item_count):
item = folder_item.child(i)
entry = [item.data(_url_role).toString(), item.text()]
icon = item.icon()
if not icon.isNull():
icon_sizes = icon.availableSizes()
try:
largest_size = icon_sizes[len(icon_sizes) -1]
icon_file_name = '{}/icon{:02}_{:02}_{}.png'.format(directory, f, i, /
/ largest_size.width())
icon.pixmap(largest_size).save(icon_file_name, 'PNG')
entry.append(icon_file_name)
except:pass
result.append(entry)
return result
def add_tool_bar_bookmark(self, url, title, icon):
# 收藏书签的方法
found, r = self.exist_url_dataItem(self._model.item(0, 0),url)
# 判断书签是否存在于书签模型
if found:self._model.item(0, 0).removeRow(r)
# 如存在,则删除
self._model.item(0, 0).insertRow(0,self._create_item(url,title, icon))
# 把新书签添加到书签数据模型self._model.item(0, 0)的最前面
def exist_url_dataItem(self,dataModel,Qurl):
# 判断书签是否存在于书签模型变量的方法
row_count = dataModel.rowCount()
for r in range(0, row_count):
item = dataModel.child(r)
url = item.data().toString()
if url==Qurl.toString():return True,r
# 如存在,则返回True和索引号
return False,-1
def _populate_actions(self, parent_item, target_object, first_action):
# 为新加的书签添加Qaction的方法
existing_actions = target_object.actions()
# 获取当前变量action数组
existing_action_count = len(existing_actions)
# 获取当前变量action数组的长度
a = first_action
# 添加的起始位置
row_count = parent_item.rowCount()
# 父变量的长度
for r in range(0, row_count):
# 遍列父变量,为新书签添加Qaction动作
item = parent_item.child(r)
title,icon,url = item.text(), item.icon(), item.data(_url_role)
if a < existing_action_count:
action = existing_actions[a]
if (title != action.toolTip()):
action.setText(BookmarkWidget.short_title(title))
action.setIcon(icon)
action.setToolTip(title)
action.setData(url)
action.setVisible(True)
else:
action = target_object.addAction(icon,BookmarkWidget.short_title(title))
action.setToolTip(title)
action.setData(url)
action.setIconVisibleInMenu(True)
action.triggered.connect(self._action_activated)
a = a + 1
def _remove_item_from_bookmarks_common(self, webview, item_Qurl,item_Tooltip, /
/ del_str, src_model):
# 从书签变量中删除一个书签的方法
button = QMessageBox.question(webview, "删除", del_str + "\"{}\"吗 ". /
/ format(item_Tooltip),QMessageBox.Yes | QMessageBox.No)
if button == QMessageBox.Yes:
# 选择删除,执行以下代码
row_count = src_model.rowCount()
for r in range(0, row_count):
item = src_model.child(r)
title = item.text()
url = item.data(_url_role)
if item_Qurl==url and item_Tooltip==title:
src_model.removeRow(r)
self.write_bookmarks()
break
def write_bookmarks(self):
# 保存书签内容到本地bookmarks.json文件的方法
dir_path = self._config_dir()
native_dir_path = QDir.toNativeSeparators(dir_path)
dir = QFileInfo(dir_path)
if not dir.isDir():
if not QDir(dir.absolutePath()).mkpath(dir.fileName()):
warnings.warn('Cannot create {}.'.format(native_dir_path), RuntimeWarning)
return
serialized_model = self._serialize_model(self._model, dir_path)
bookmark_file_name = os.path.join(native_dir_path, 'bookmarks.json')
with open(bookmark_file_name, 'w') as bookmark_file:
json.dump(serialized_model, bookmark_file, indent = 4)
def _read_bookmarks(self):
# 读取本地书签bookmarks.json文件或默认书签的方法
bookmark_file_name = os.path.join(QDir.toNativeSeparators( /
/ self._config_dir()),'bookmarks.json')
if os.path.exists(bookmark_file_name):
return json.load(open(bookmark_file_name))
return _default_bookmarks
……省略无关代码
@staticmethod
def short_title(t):
# 获取网页短标题的方法
isEnglish = all(ord(c) < 128 for c in t)
# 判断网页标题是否为英文
if isEnglish == True:n=38
else:n=19
return t[0:n]
class Browser(myQMainWindow):
# 自定义Browser类,继承myQMainWindow类
def __init__(self, mainWin, webview=None):
super().__init__(mainWin)
self.mainWin,self.webview,self.part = mainWin, webview, ''
#初始化三变量self.mainWin,self.webview,self.part,self.part储存全屏播放视频父实例
self.initUI()
# 调用初始化界面的方法
def initUI(self):
# 初始化界面的方法
if self.webview == None:
# 如是第一个页面
self.webview = WebView(self)
# 调WebView类实例化
self.webview.load(QUrl("http://www.hao123.com/"))
# 把网页加载导航页http://www.hao123.com/
elif self.webview == '':self.webview = WebView(self)
# 创建空白新页签
self.webview.setZoomFactor(1.35)
# 把网页显示字号放大35%
self.webview.page().titleChanged.connect(self._title_changed)
# 把网页标题改变信号关联到_title_changed方法
self.webview.page().iconChanged.connect(self._icon_changed)
# 把网页图标改变信号关联到_icon_changed方法
self.initToolbar(self.webview)
# 调用 initToolbar 方法
self.setCentralWidget(self.webview)
# 把网页实例到页签窗口的中央
self.webview.setContextMenuPolicy(Qt.CustomContextMenu)
# 设置网页为自定义右击上下文菜单
self.webview.customContextMenuRequested.connect(self.context_webmenu_event)
#设置网页自定义右击文菜单的请求关联方法context_webmenu_event
webview_group.append(self.webview)
# 向网页实例数组变量添加该网页实例
webview_parent_group.append(self.webview.parent())
# 向网页父实例数组变量添加该网页父实例
if self.mainWin.INDEX==0:
# 假如是第一个页签, 那么执行以下代码
self.webview.setParent(None)
# 把本网页实例的父实例设置为None
self.webview.showFullScreen()
# 把本网页实例最大化显示
webview_parent_group[0].grabKeyboard()
# 把本网页父实例设置为捕获键盘, 以便进入全屏模式
……省略无关代码
def context_webmenu_event(self, point):
# 网页右击菜单处理的方法
if self.webview == self.sender():
webview_parent_group[self.mainWin.INDEX].grabKeyboard()
# 让当前窗口捕获键盘,进入全屏模式
linkUrl = self.webview.page().contextMenuData().linkUrl().toString()
# 获取网页的Url
editable = self.webview.page().contextMenuData().isContentEditable()
# 获取网页的编辑状态
mediaType = self.webview.page().contextMenuData().mediaType()
# 获取控件的类型
context_menu = QMenu()
# 构建鼠标右击菜单
close_action = context_menu.addAction(QIcon('img/close.jpg'), "关闭")
context_menu.addAction(QAction(QIcon('img/bookmark_toolbar.jpg'), /
/ "我的书签", self,triggered=self.mainWin.toolbar_bookmarks))
context_menu.addAction(QAction(QIcon('img/view_history.jpg'),"浏览足迹", self, /
/ triggered=self.mainWin.show_browsing_history))
context_menu.addAction(QAction(QIcon('img/bookmark_save_to_toolbar.jpg'), /
/ "收藏书签", self, triggered=self.mainWin.add_tool_bar_bookmark))
……省略无关代码
def _icon_changed(self, icon):
# 网页图标改变的处理方法
self.mainWin.tabWidget.setTabIcon(self.mainWin.INDEX, icon)
url,title = self.webview.url(),self.webview.title()
found, r = self.mainWin.bookmark_widget.exist_url_dataItem(self.mainWin. /
/ bookmark_widget._model.item(1, 0), url)
if found: self.mainWin.bookmark_widget._model.item(1, 0).removeRow(r)
# 如浏览足迹存在这个网址,则把相应变量_model.item(1, 0)中的网址删除
self.mainWin.bookmark_widget._model.item(1, 0).insertRow( /
/ 0, self.mainWin.bookmark_widget._create_item(url, title,icon))
# 把该网址添加到相应变量_model.item(1, 0)的第一个
class MyBrowser(myQMainWindow):
# 自定义MyBrowser主窗口类,继承myQMainWindow类
def __init__(self):
super().__init__()
self.initWinTab()
# 初始化主窗口和页签
self.newTab()
# 创建第一个新页签
def initWinTab(self):
# 初始化主窗口和页签的方法
self.setWindowTitle('hahayaya 极速简约防盗 Linux 全屏浏览器')
self.setWindowFlags(Qt.WindowCloseButtonHint)
# 设置主窗口只有一个关闭按钮,没有最大化和最小化按钮,实现防盗
self.setWindowIcon(QIcon('img/hahayaya_logo1.png'))
self.sougou_tool_bar = QToolBar('')
# 激活显示搜狗输入法的工具栏,内容为空,辅助用途
self.tabWidget = QTabWidget()
self.tabWidget.setTabShape(QTabWidget.Triangular)
# 设置页签风格为梯形状
self.tabWidget.setTabsClosable(True)
# 设置页签可关闭
self.tabWidget.tabCloseRequested.connect(self.close_Tab)
# 设置页签关闭方法是close_Tab
self.tabWidget.currentChanged.connect(self.changeTab)
self.tabWidget.tabBarClicked.connect(self.clickTab)
self.setCentralWidget(self.tabWidget)
self.bookmark_widget = BookmarkWidget()
# 书签类实例化
self.bookmark_widget.open_bookmark.connect(self.load_url)
self.bookmark_toolbar = myQMenu('我的书签列表')
self.bookmark_toolbar.setContextMenuPolicy(Qt.CustomContextMenu)
self.bookmark_toolbar.customContextMenuRequested.connect( /
/ self.context_toolbar_event)
# 书签窗口右击菜单关联context_toolbar_event方法
self.bookmark_toolbar.setToolTipsVisible(True)
self.showMaximized()
def load_url(self, url):
# 当前网页加载新网址方法
webview_group[self.INDEX].setUrl(url)
found, r = self.bookmark_widget.exist_url_dataItem(self.bookmark_widget./
/_model.item(0, 0), url)
# 判断当前书签是否包含本网址
if found:
# 如网址在书签中存在,则先删除后置顶书签并保存
item = self.bookmark_widget._model.item(0, 0).child(r)
title,icon = item.text(), item.icon()
self.bookmark_widget._model.item(0, 0).removeRow(r)
self.bookmark_widget._model.item(0, 0)./
/ insertRow(0, self.bookmark_widget._create_item(url,title, icon))
self.bookmark_widget.write_bookmarks()
def add_tool_bar_bookmark(self):
# 收藏书签的方法
url = webview_group[self.INDEX].url()
icon,title = self.tabWidget.tabIcon(self.INDEX),self.tabWidget.tabToolTip(self.INDEX)
self.bookmark_widget.add_tool_bar_bookmark(url, title, icon)
# 添加书签
self.bookmark_widget.write_bookmarks()
# 保存书签
self.toolbar_bookmarks()
# 显示书签
def toolbar_bookmarks(self):
# 书签窗口显示方法
self.bookmark_footprint_common(self.bookmark_widget./
/_model.item(0, 0),self.bookmark_toolbar)
def bookmark_footprint_common(self,src_model,myQmenu):
# 书签和浏览足迹显示的公用方法
rows = src_model.rowCount()
cols = int(rows/37)
if rows % 37 > 0: cols += 1
cols = min(3,cols)
myQmenu.setVisible(True)
myQmenu.resize(cols*384,1050)
myQmenu.move(553,0)
mouse = QCursor()
mouse.setPos(630,17)
# 把光标定位到第一行
def context_toolbar_event(self, point):
# 书签菜单右击删除的方法
action = self.bookmark_toolbar.actionAt(point)
if action is not None:
context_menu = QMenu()
remove_action = context_menu.addAction("删除")
current_Qurl,current_Tooltip = action.data(),action.toolTip()
chosen_action = context_menu.exec_(QCursor.pos())
if chosen_action == remove_action:self.bookmark_widget./
/_remove_item_from_bookmarks_common(webview_group[self.INDEX],current_Qurl
/,current_Tooltip, "真的想删除书签: ", self.bookmark_widget._model.item(0,0))
……省略无关代码
if __name__ == "__main__":
# 主程序
argvs = sys.argv
argvs.append("--no-sandbox")
QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL)
app = QApplication(argvs)
window = MyBrowser()
# 实例化主窗口和加载首页面
window.show()
# 显示主窗口
sys.exit(app.exec_())
机译: 机动车,具有浏览器程序,该浏览器程序加载可通过书签通过各个预设调用命令基于书签调用的Internet页面,并在浏览器程序的不同选项卡或窗口中显示页面
机译: 用于编辑智能手机浏览器的书签的方法,以及具有用于智能手机浏览器的书签的编辑程序的计算机可读记录介质
机译: 删除智能手机浏览器上的书签历史的方法,以及带有智能手机浏览器上的书签的删除程序的计算机可读记录介质