├── util
├── logger.py
├── browser_util.py
├── thread_util.py
├── git_util.py
├── my_calendar.py
├── version_util.py
├── send_win_message_util.py
├── show_image_util.py
├── winreg_util.py
├── time_util.py
├── resolution_util.py
├── card_util.py
├── ip_change_util.py
├── count_down_util.py
├── style_util.py
└── time_calculate.py
├── img
├── icon
│ ├── icon.ico
│ └── icon.png
├── drinking
│ ├── history.png
│ ├── refresh.png
│ └── setting.png
└── weather
│ ├── black80.png
│ ├── blue80.png
│ ├── white80.png
│ └── lightBlue80.png
├── version_util.py
├── my_component
├── MyQLabel.py
└── MyListWidget.py
├── config
├── special_list_config.py
├── todo_list_config.py
├── drinking_setting.py
├── micro_blog_config.py
├── start_module_list_config.py
├── city_setting.py
└── drinking_config.py
├── compiled_resources.qrc
├── thread_list
├── time_thread.py
├── image_thread.py
├── keyboard_thread.py
├── schedule_thread.py
└── start_module_list_thread.py
├── LICENSE
├── module
├── icon_tool.py
├── drink_paint.py
├── click_connect.py
├── init_module.py
└── update_info.py
├── README.md
├── record.py
├── .gitignore
├── record_form.py
├── record_form.ui
├── setting.py
├── new_todo.py
├── get_info
├── get_tophub_blog_info.py
├── get_schedule_info.py
├── get_weather_info.py
└── get_micro_blog_info.py
├── city.py
├── setting_form.py
├── city_form.py
├── setting_form.ui
├── city_form.ui
├── new_todo_form.py
└── new_todo_form.ui
/util/logger.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/util/logger.py
--------------------------------------------------------------------------------
/img/icon/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/icon/icon.ico
--------------------------------------------------------------------------------
/img/icon/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/icon/icon.png
--------------------------------------------------------------------------------
/img/drinking/history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/drinking/history.png
--------------------------------------------------------------------------------
/img/drinking/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/drinking/refresh.png
--------------------------------------------------------------------------------
/img/drinking/setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/drinking/setting.png
--------------------------------------------------------------------------------
/img/weather/black80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/weather/black80.png
--------------------------------------------------------------------------------
/img/weather/blue80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/weather/blue80.png
--------------------------------------------------------------------------------
/img/weather/white80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/weather/white80.png
--------------------------------------------------------------------------------
/util/browser_util.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 |
4 | def open_url(url):
5 | os.popen('start ' + str(url))
6 |
--------------------------------------------------------------------------------
/img/weather/lightBlue80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baby7/baby7-desktop-tool/HEAD/img/weather/lightBlue80.png
--------------------------------------------------------------------------------
/version_util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'version_util.py'
4 | #
5 | # Created by: PySide2 UI code generator 5.15.4
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 |
--------------------------------------------------------------------------------
/util/thread_util.py:
--------------------------------------------------------------------------------
1 | # 关闭单个线程
2 | def close_one_thread(thread):
3 | if thread is not None:
4 | thread.active = False
5 | thread.terminate()
6 | thread.quit()
7 | thread.wait()
8 | while True:
9 | if thread is None or thread.isFinished() is True:
10 | break
11 | thread.active = False
12 | thread.terminate()
13 | thread.quit()
14 | thread.wait()
15 |
--------------------------------------------------------------------------------
/my_component/MyQLabel.py:
--------------------------------------------------------------------------------
1 | from PySide2.QtWidgets import QLabel
2 | from PySide2.QtCore import Signal
3 |
4 |
5 | class MyQLabel(QLabel):
6 |
7 | # 自定义单击信号
8 | clicked = Signal()
9 | # 自定义双击信号
10 | DoubleClicked = Signal()
11 |
12 | def __init__(self, parent):
13 | super().__init__(parent=parent)
14 |
15 | # 重写鼠标单击事件
16 | def mousePressEvent(self, QMouseEvent): # 单击
17 | self.clicked.emit()
18 |
19 | # 重写鼠标双击事件
20 | def mouseDoubleClickEvent(self, e): # 双击
21 | self.DoubleClicked.emit()
22 |
--------------------------------------------------------------------------------
/util/git_util.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 |
4 | def git_state():
5 | result_list = os.popen('git config --list').readlines()
6 | for result in result_list:
7 | if "proxy" in result:
8 | return True
9 | return False
10 |
11 |
12 | def open_git():
13 | os.system('git config --global http.proxy socks5://127.0.0.1:7890 && '
14 | 'git config --global https.proxy socks5://127.0.0.1:7890')
15 |
16 |
17 | def close_git():
18 | os.system('git config --global --unset http.proxy && git config --global --unset https.proxy')
19 |
--------------------------------------------------------------------------------
/config/special_list_config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | def get_special_list_config():
6 | special_list_config = []
7 | config_path = str(os.getcwd()) + r"\config\special_list.json"
8 | if os.path.exists(config_path):
9 | with open(config_path, 'r', encoding='utf-8') as f:
10 | config_len = len(f.readlines())
11 | with open(config_path, 'r', encoding='utf-8') as f:
12 | if config_len != 0:
13 | special_list_config = json.load(f)
14 | if special_list_config is None or special_list_config == []:
15 | special_list_config = []
16 | return special_list_config
17 |
--------------------------------------------------------------------------------
/util/my_calendar.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtCore, QtGui, QtWidgets
2 |
3 |
4 | class MyCalendar(QtWidgets.QCalendarWidget):
5 |
6 | focus_date_list = [
7 | '2023-02-10',
8 | '2023-02-11',
9 | '2023-02-12',
10 | ]
11 |
12 | def __init__(self, parent=None):
13 | QtWidgets.QCalendarWidget.__init__(self, parent)
14 |
15 | def paintCell(self, painter, rect, date):
16 | QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date)
17 | if str(date.toString("yyyy-MM-dd")) in self.focus_date_list:
18 | painter.setPen(QtGui.QColor(255, 61, 64))
19 | painter.drawText(rect.center(), " *")
20 |
--------------------------------------------------------------------------------
/compiled_resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | img/drinking/history.png
5 | img/drinking/refresh.png
6 | img/drinking/setting.png
7 | img/icon/icon.ico
8 | img/icon/icon.png
9 | img/weather/black80.png
10 | img/weather/blue80.png
11 | img/weather/lightBlue80.png
12 | img/weather/white80.png
13 |
14 |
--------------------------------------------------------------------------------
/thread_list/time_thread.py:
--------------------------------------------------------------------------------
1 | # -- coding: utf-8 --
2 | import time
3 | import datetime
4 | import traceback
5 | from PySide2.QtCore import QThread, Signal
6 |
7 |
8 | # 定时线程(一分钟提醒一次)
9 | class TimeThread(QThread):
10 | active = True
11 | # 触发器
12 | zero_trigger = Signal(str)
13 |
14 | def __init__(self, parent=None):
15 | super().__init__(parent)
16 |
17 | def stop(self):
18 | self.terminate()
19 |
20 | def run(self):
21 | while self.active:
22 | try:
23 | time.sleep(0.5)
24 | datetime_now = datetime.datetime.now()
25 | second = datetime_now.second
26 | if int(second) == 0:
27 | self.zero_trigger.emit(str(datetime_now.strftime("%Y-%m-%d %H:%M:%S")))
28 | time.sleep(2)
29 | except Exception:
30 | traceback.print_exc()
31 |
--------------------------------------------------------------------------------
/util/version_util.py:
--------------------------------------------------------------------------------
1 | update_info = """版本:
2 |
3 | V1.0.0: 初始版本
4 | V1.1.0: 增加常用按钮,用来复制时间段
5 | V1.1.1: 定期刷新日期
6 | V1.2.0: 下方【摸鱼人日历】卡片单击可以弹出查看大图
7 | V1.3.0: 替换倒计时模块为喝水记录模块、美化下方卡片
8 |
9 | V2.0.0
10 | 增加更新记录菜单
11 | 增加喝水设置功能
12 | 增加喝水记录功能,喝水现在可以自动保存,零点重新计数
13 | 去除【摸鱼人日历】卡片
14 | Looking卡片新增: 摸鱼人日历、必应每日一图
15 | Reading卡片新增: 历史上的今天|生活小窍门|脑筋急转弯|彩虹屁|心语|毒鸡汤|土味情话
16 |
17 | V2.0.1: Reading卡片修改:历史上的今天调整展示、优化隐藏状态下性能问题
18 | V2.0.2: 修复节假日报错的问题
19 | V2.0.3: 部分操作错误时进行弹窗,不再卡退;秒读新加一个源,第一个源失败自动使用第二个源
20 | V2.0.4: 雨天换成蓝色的图标做提示
21 | V2.1.0: 天气可以选择城市(之前是写死)
22 | V2.1.1: 增加说明菜单
23 | V2.2.0: 调整样式,V3.0前置版本
24 | V2.3.0: 框架调整,另增加微博外的五个热搜
25 | V2.4.0: 界面增加交互,另外增加退出按钮
26 | V2.5.0: 修复打不开的问题,修复部分情况下界面没有显示在顶部的问题,剔除tkinter模块
27 | V2.6.0: 增加微博刷新按钮,增加开机自启动按钮
28 | V2.6.1: 优化点击托盘图标弹出工具的操作
29 |
30 | """
31 |
32 | about_info = """说明:
33 | 1. 可以将托盘区小图标拖到任务栏,然后点击小图标可以隐藏和展示。
34 | (任务栏就是屏幕下面的小长条,托盘区就是点击任务栏右侧的向上箭头后出来的图标区域)
35 | 2. 使用快捷键Alt+1可以隐藏和展示。
36 | """
--------------------------------------------------------------------------------
/util/send_win_message_util.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 | import datetime
4 |
5 | from winotify import Notification
6 |
7 |
8 | def send_message(app_name, title, descript, url=None):
9 | """
10 | 发送Win10右下角弹框提醒
11 | :param app_name: 程序名称
12 | :param title: 消息标题
13 | :param descript: 消息内容
14 | :param url: 点击跳转的地址
15 | """
16 | if url is not None:
17 | Notification(app_id=app_name + " " + str(datetime.datetime.now().strftime("%H:%M:%S")),
18 | title=title,
19 | msg=descript,
20 | icon=":img/icon/icon.png",
21 | launch=url).show()
22 | else:
23 | Notification(app_id=app_name + " " + str(datetime.datetime.now().strftime("%H:%M:%S")),
24 | title=title,
25 | msg=descript,
26 | icon=":img/icon/icon.png").show()
27 | time.sleep(1)
28 |
--------------------------------------------------------------------------------
/config/todo_list_config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | def get_todo_list_config():
6 | todo_list_config = {}
7 | config_path = str(os.getcwd()) + r"\config\todo_list.json"
8 | if os.path.exists(config_path):
9 | with open(config_path, 'r', encoding='utf-8') as f:
10 | config_len = len(f.readlines())
11 | with open(config_path, 'r', encoding='utf-8') as f:
12 | if config_len != 0:
13 | todo_list_config = json.load(f)
14 | if todo_list_config is None or todo_list_config == {}:
15 | todo_list_config = {"proceed_todo_list": [], "complete_todo_list": []}
16 | return todo_list_config
17 |
18 |
19 | def set_todo_list_config(new_todo_list_config):
20 | todo_list_config = new_todo_list_config
21 | config_path = str(os.getcwd()) + r"\config\todo_list.json"
22 | with open(config_path, 'w', encoding='utf-8') as f:
23 | json.dump(todo_list_config, f, ensure_ascii=False)
24 | return todo_list_config
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright 2017 baiy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/config/drinking_setting.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | def get_drinking_setting():
6 | drink_config = {}
7 | config_path = str(os.getcwd()) + r"\config\drinking_setting.json"
8 | if os.path.exists(config_path):
9 | with open(config_path, 'r') as f:
10 | config_len = len(f.readlines())
11 | with open(config_path, 'r') as f:
12 | if config_len != 0:
13 | drink_config = json.load(f)
14 | if len(drink_config) == 0:
15 | drink_config = {
16 | "drinking_count": 8, # 喝水数量
17 | "view_message": "positive" # 窗口信息 正着计数(positive)/倒着计数(negative)
18 | }
19 | with open(config_path, 'w') as f:
20 | json.dump(drink_config, f)
21 | return drink_config
22 |
23 |
24 | def set_drinking_setting(new_drink_config):
25 | drink_config = new_drink_config
26 | config_path = str(os.getcwd()) + r"\config\drinking_setting.json"
27 | with open(config_path, 'w') as f:
28 | json.dump(drink_config, f)
29 | return drink_config
30 |
--------------------------------------------------------------------------------
/config/micro_blog_config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | def get_micro_blog_config():
6 | micro_blog_config = {}
7 | config_path = str(os.getcwd()) + r"\config\micro_blog.json"
8 | if os.path.exists(config_path):
9 | with open(config_path, 'r', encoding='utf-8') as f:
10 | config_len = len(f.readlines())
11 | with open(config_path, 'r', encoding='utf-8') as f:
12 | if config_len != 0:
13 | micro_blog_config = json.load(f)
14 | if micro_blog_config is None or micro_blog_config == {}:
15 | micro_blog_config = {
16 | "active": False,
17 | "screen_word_list": [],
18 | "screen_type_list": []
19 | }
20 | return micro_blog_config
21 |
22 |
23 | def set_micro_blog_config(new_micro_blog_config):
24 | micro_blog_config = new_micro_blog_config
25 | config_path = str(os.getcwd()) + r"\config\micro_blog.json"
26 | with open(config_path, 'w', encoding='utf-8') as f:
27 | json.dump(micro_blog_config, f, ensure_ascii=False)
28 | return micro_blog_config
29 |
--------------------------------------------------------------------------------
/config/start_module_list_config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | def get_start_module_list_config():
6 | start_module_list_config = {}
7 | config_path = str(os.getcwd()) + r"\config\start_module_list.json"
8 | if os.path.exists(config_path):
9 | with open(config_path, 'r', encoding='utf-8') as f:
10 | config_len = len(f.readlines())
11 | with open(config_path, 'r', encoding='utf-8') as f:
12 | if config_len != 0:
13 | start_module_list_config = json.load(f)
14 | if start_module_list_config is None or start_module_list_config == {}:
15 | start_module_list_config = {"start_module_list": []}
16 | return start_module_list_config
17 |
18 |
19 | def set_start_module_list_config(new_start_module_list_config):
20 | start_module_list_config = new_start_module_list_config
21 | config_path = str(os.getcwd()) + r"\config\start_module_list.json"
22 | with open(config_path, 'w', encoding='utf-8') as f:
23 | json.dump(start_module_list_config, f, ensure_ascii=False)
24 | return start_module_list_config
25 |
--------------------------------------------------------------------------------
/config/city_setting.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | def get_city_setting():
6 | drink_config = {}
7 | # 判断config文件夹是否存在
8 | if not os.path.exists(str(os.getcwd()) + r"\config"):
9 | os.mkdir(str(os.getcwd()) + r"\config")
10 | # 判断config文件是否存在
11 | config_path = str(os.getcwd()) + r"\config\city_setting.json"
12 | if os.path.exists(config_path):
13 | with open(config_path, 'r', encoding='utf-8') as f:
14 | config_len = len(f.readlines())
15 | with open(config_path, 'r', encoding='utf-8') as f:
16 | if config_len != 0:
17 | drink_config = json.load(f)
18 | if len(drink_config) == 0:
19 | drink_config = {
20 | "province": "",
21 | "city": "",
22 | "county": "",
23 | "countyName": ""
24 | }
25 | with open(config_path, 'w', encoding='utf-8') as f:
26 | json.dump(drink_config, f)
27 | return drink_config
28 |
29 |
30 | def set_city_setting(new_drink_config):
31 | drink_config = new_drink_config
32 | config_path = str(os.getcwd()) + r"\config\city_setting.json"
33 | with open(config_path, 'w', encoding='utf-8') as f:
34 | json.dump(drink_config, f)
35 | return drink_config
36 |
--------------------------------------------------------------------------------
/thread_list/image_thread.py:
--------------------------------------------------------------------------------
1 | import time
2 | import traceback
3 | import requests
4 | from PySide2.QtCore import *
5 |
6 |
7 | # 加载图片
8 | def set_data(url, label_data):
9 | try:
10 | response = requests.get(url)
11 | label_data['byte'] = QByteArray(response.content)
12 | except Exception as e:
13 | traceback.print_exc()
14 |
15 |
16 | class ImgThread(QThread):
17 | active = True
18 | # 触发器
19 | end_trigger = Signal(dict) # 使用结束触发器
20 |
21 | # 图片地址
22 | image_url_data_list = None
23 | label_image_data = None
24 |
25 | def __init__(self, parent=None, url_data=None):
26 | super().__init__(parent)
27 | self.image_url_data_list = url_data
28 |
29 | def stop(self):
30 | self.terminate()
31 |
32 | def run(self):
33 | for img_url_data in self.image_url_data_list:
34 | self.label_image_data = {
35 | "byte": None,
36 | "buffer": None,
37 | "gif": None,
38 | "name": img_url_data['name']
39 | }
40 | set_data(img_url_data['url'], self.label_image_data)
41 | self.end_trigger.emit(self.label_image_data)
42 | if not self.active:
43 | return
44 | time.sleep(1)
45 |
--------------------------------------------------------------------------------
/config/drinking_config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 |
5 | def get_drinking_config():
6 | drinking_config = []
7 | config_path = str(os.getcwd()) + r"\config\drinking_config.json"
8 | if os.path.exists(config_path):
9 | with open(config_path, 'r') as f:
10 | config_len = len(f.readlines())
11 | with open(config_path, 'r') as f:
12 | if config_len != 0:
13 | drinking_config = json.load(f)
14 | drinking_config_result = []
15 | for record in drinking_config:
16 | drinking_config_result.append(record)
17 | return drinking_config_result
18 |
19 |
20 | def set_drinking_config(add_record):
21 | drinking_config = get_drinking_config()
22 | config_path = str(os.getcwd()) + r"\config\drinking_config.json"
23 | if os.path.exists(config_path):
24 | tag = True
25 | for record in drinking_config:
26 | if record['date'] == add_record['date']:
27 | record['count'] = add_record['count']
28 | tag = False
29 | break
30 | if tag:
31 | drinking_config.append(add_record)
32 | else:
33 | drinking_config = [add_record]
34 | with open(config_path, 'w') as f:
35 | json.dump(drinking_config, f)
36 | return drinking_config
37 |
--------------------------------------------------------------------------------
/module/icon_tool.py:
--------------------------------------------------------------------------------
1 | import os
2 | from PySide2.QtGui import QIcon
3 | from PySide2.QtWidgets import (QMenu, QAction, QSystemTrayIcon)
4 |
5 |
6 | # 设置图标
7 | def set_icon(main_object):
8 | main_object.sys_icon = QIcon(":img/icon/icon.ico")
9 | main_object.setWindowIcon(main_object.sys_icon)
10 |
11 |
12 | # 设置托盘图标
13 | def set_tray_icon(main_object):
14 | menu = QMenu(main_object)
15 | menu.addAction(QAction(u'城市选择', main_object, triggered=main_object.open_city_view))
16 | menu.addAction(QAction(u'喝水设置', main_object, triggered=main_object.open_drinking_setting_view))
17 | menu.addAction(QAction(u'喝水记录', main_object, triggered=main_object.open_drinking_record_view))
18 | menu.addAction(QAction(u'更新记录', main_object, triggered=main_object.open_update_view))
19 | menu.addAction(QAction(u'说明', main_object, triggered=main_object.open_about_view))
20 | menu.addAction(QAction(u'退出', main_object, triggered=main_object.quit_before))
21 | menu.setStyleSheet("background: rgb(255, 255, 255); color: rgb(0, 0, 0);")
22 | main_object.tray_icon = QSystemTrayIcon(main_object)
23 | main_object.tray_icon.setIcon(main_object.sys_icon)
24 | main_object.tray_icon.setContextMenu(menu)
25 | main_object.tray_icon.activated.connect(main_object.show_hide_form)
26 | main_object.tray_icon.show()
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > # 七仔的桌面工具
2 |
3 | ### 该版本暂停更新,【新版本Github】请点击下方链接访问
4 |
5 | [https://github.com/baby7/agile-tiles](https://github.com/baby7/agile-tiles)
6 |
7 | ### 介绍
8 |
9 | Windows桌面端软件,摸鱼办公神器
10 |
11 | 拥有多种卡片自定义布局,隐藏到侧边需要使用时弹出(可以鼠标或快捷键唤出)
12 |
13 | #### 主卡片
14 | * 本地文件快捷搜索(基于everything)
15 | * 快捷键截图、屏幕取色
16 | * 翻译(同时接入截图识别并翻译)
17 | * AI对话(多种智能体)
18 | * TODO(待办事项)功能
19 | * 各大平台实时热搜
20 | * 音乐播放器、小说阅读器
21 | * 有趣图文(摸鱼人日历、kfc梗图文案、萌宠图片、历史上的今天、随机心语)
22 | * 热门网站链接聚合
23 |
24 | #### 小卡片
25 | * Epic Steam 喜加一资讯
26 | * Bilibili粉丝量
27 | * 自定义快捷方式(网址、exe文件、文件夹或普通文件)
28 | * LCD时钟、日历、天气预报
29 | * 喝水记录、今天吃什么、电子木鱼
30 | * 倒数日、圆盘时钟、英语单词
31 | * 自定义图片、工作日、电脑监控
32 | * 灵感提示词、时间进度条、搜索
33 | * 古诗词、答案之书、一言
34 |
35 | #### 工具箱模块
36 | * 文件批量操作工具、屏幕取色工具
37 | * Json格式化工具、编解码工具、颜色转换器
38 | * 时间 时区 时间戳的计算器
39 | * 图片批量转表格工具
40 | * 视频进度条生成器、笔记本电池健康曲线
41 | * 这班值不值得上、记仇生成器
42 | * 中国房贷计算器、中国家庭称谓计算器
43 | * BMI计算器
44 |
45 | ### 运行展示(双主题)
46 |
47 | 
48 |
49 | ## Star History
50 |
51 | [](https://www.star-history.com/#baby7/baby7-desktop-tool&Date)
52 |
53 | ### 下载
54 |
55 | #### 蓝奏云
56 |
57 | 链接: [https://agiletiles.lanzoue.com/s/agiletiles](https://agiletiles.lanzoue.com/s/agiletiles)
--------------------------------------------------------------------------------
/util/show_image_util.py:
--------------------------------------------------------------------------------
1 | import os
2 | from PySide2.QtWidgets import QApplication, QLabel, QDialog
3 | from PySide2.QtGui import QPixmap
4 |
5 | def show_image_window(main_object, title, image_data):
6 | try:
7 | if image_data is None:
8 | return
9 | desktop = QApplication.desktop().screenGeometry(0) # 多显示屏,显示主屏
10 | desktop_width = desktop.width()
11 | desktop_height = desktop.height() - 100
12 | with open('collection.jpg', 'wb') as tmp:
13 | tmp.write(image_data)
14 | main_object.dialog_fault = QDialog()
15 | main_object.dialog_fault.setWindowTitle(title)
16 | image_path = "collection.jpg"
17 | pic = QPixmap(image_path)
18 | width = pic.width()
19 | height = pic.height()
20 | if width > desktop_width:
21 | height = int((desktop_width / width) * height)
22 | width = desktop_width
23 | if height > desktop_height:
24 | width = int((desktop_height / height) * width)
25 | height = desktop_height
26 | label_pic = QLabel("show", main_object.dialog_fault)
27 | label_pic.setPixmap(pic)
28 | label_pic.setGeometry(0, 0, width, height)
29 | label_pic.setScaledContents(True)
30 | main_object.dialog_fault.exec_()
31 | os.remove("collection.jpg")
32 | except Exception as e:
33 | print(e)
--------------------------------------------------------------------------------
/record.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 | from PySide2.QtCore import Qt
3 | from qframelesswindow import AcrylicWindow
4 | from record_form import Ui_Form
5 | from PySide2 import QtCore
6 |
7 | from PySide2.QtCore import *
8 | from PySide2.QtWidgets import *
9 | from PySide2.QtGui import *
10 |
11 | import config.drinking_config as drinking_config
12 |
13 |
14 | class RecordWindow(AcrylicWindow, Ui_Form):
15 |
16 | def __init__(self, parent=None):
17 | super(RecordWindow, self).__init__(parent=parent)
18 |
19 | self.setupUi(self)
20 | self.setWindowFlag(QtCore.Qt.Tool)
21 | # 设置标题栏
22 | self.setWindowTitle("七仔的桌面工具 - 喝水记录")
23 | self.titleBar.minBtn.close()
24 | self.titleBar.maxBtn.close()
25 | drink_list = drinking_config.get_drinking_config()
26 | write_table_view(self.drink_table_view, drink_list,['日期', '杯数'], ['date', 'count'])
27 | self.drink_table_view.setColumnWidth(0, 130)
28 | self.drink_table_view.setColumnWidth(1, 80)
29 |
30 |
31 | # 渲染列表
32 | def write_table_view(table_view, data_list, title_list, name_list):
33 | model = QStandardItemModel(len(data_list), len(name_list))
34 | model.setHorizontalHeaderLabels(title_list)
35 | for row in range(len(data_list)):
36 | for line in range(len(name_list)):
37 | model.setItem(row, line, QStandardItem(str(data_list[row][name_list[line]])))
38 | table_view.setModel(model)
39 | # 设置滚动条
40 | table_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
41 | # 设置表头不可点击
42 | table_view.horizontalHeader().setSectionsClickable(False)
43 | table_view.verticalHeader().setSectionsClickable(False)
44 | # 设置禁止编辑
45 | table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
46 | # 设置只能选中一行
47 | table_view.setSelectionMode(QAbstractItemView.SingleSelection)
48 | # 设置只能选中整行
49 | table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
50 | # 行高
51 | table_view.verticalHeader().setDefaultSectionSize(15)
52 |
--------------------------------------------------------------------------------
/thread_list/keyboard_thread.py:
--------------------------------------------------------------------------------
1 | # -- coding: utf-8 --
2 | from pynput import keyboard
3 | from PySide2.QtCore import QThread, Signal
4 |
5 |
6 | ALT = False
7 | # Q = False
8 | ONE = False
9 |
10 |
11 | # 本文中只用到ALT和C其他的备用(在我的小工具包里ALT+Z是截屏、ALT+x是截屏文字识别)自行扩展
12 | def listen(keyboard_trigger): # 键盘监听函数
13 | # def on_press(key):
14 | # global ALT, Q
15 | # if key == keyboard.Key.alt or key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
16 | # ALT = True
17 | # if key == keyboard.KeyCode(char='q') or key == keyboard.KeyCode(char='Q'):
18 | # Q = True
19 | #
20 | # if ALT and Q: # 检测到Alt和c同时按下时
21 | # Q = False
22 | # keyboard_trigger.emit("11")
23 | def on_press(key):
24 | global ALT, ONE
25 | if key == keyboard.Key.alt or key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
26 | ALT = True
27 | if key == keyboard.KeyCode(char='1'):
28 | ONE = True
29 |
30 | if ALT and ONE: # 检测到Alt和c同时按下时
31 | ONE = False
32 | keyboard_trigger.emit("11")
33 |
34 | # def on_release(key):
35 | # global ALT, Q
36 | # if key == keyboard.Key.alt or key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
37 | # ALT = False
38 | # if key == keyboard.KeyCode(char='q') or key == keyboard.KeyCode(char='Q'):
39 | # Q = False
40 |
41 | def on_release(key):
42 | global ALT, ONE
43 | if key == keyboard.Key.alt or key == keyboard.Key.alt_l or key == keyboard.Key.alt_r:
44 | ALT = False
45 | if key == keyboard.KeyCode(char='1'):
46 | ONE = False
47 |
48 | with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
49 | listener.join()
50 |
51 |
52 | # 键盘监听线程
53 | class KeyboardThread(QThread):
54 | active = True
55 | # 触发器
56 | keyboard_trigger = Signal(str)
57 |
58 | def __init__(self, parent=None):
59 | super().__init__(parent)
60 |
61 | def stop(self):
62 | self.terminate()
63 |
64 | def run(self):
65 | while self.active:
66 | listen(self.keyboard_trigger)
67 |
--------------------------------------------------------------------------------
/thread_list/schedule_thread.py:
--------------------------------------------------------------------------------
1 | # -- coding: utf-8 --
2 | import time
3 | import datetime
4 | import traceback
5 | from PySide2.QtCore import QThread, Signal
6 | from get_info import get_schedule_info
7 |
8 |
9 | # 定时更新倒计时
10 | class ScheduleThread(QThread):
11 | active = True
12 | first = True
13 | # 触发器
14 | important_trigger = Signal(str)
15 | daily_trigger = Signal(str)
16 |
17 | def __init__(self, parent=None):
18 | super().__init__(parent)
19 |
20 | def stop(self):
21 | self.terminate()
22 |
23 | def run(self):
24 | while self.active:
25 | try:
26 | time.sleep(0.5)
27 | datetime_now = datetime.datetime.now()
28 | minute = datetime_now.minute
29 | if int(minute) % 5 == 0 or self.first:
30 | self.first = False
31 | # 重要的
32 | important_schedule_list = get_schedule_info.get_important_schedule_list()
33 | important_schedule_text = ""
34 | for now_follow_date_index in range(len(important_schedule_list)):
35 | if now_follow_date_index < 7:
36 | important_schedule_text += "还有" + str(important_schedule_list[now_follow_date_index]['gap_day']) + "天 " \
37 | + important_schedule_list[now_follow_date_index]['task'] + "\n"
38 | if important_schedule_text.endswith("\n"):
39 | important_schedule_text = important_schedule_text[:-1]
40 | self.important_trigger.emit(str(important_schedule_text))
41 | # 日程
42 | daily_schedule_list = get_schedule_info.get_daily_schedule_list()
43 | daily_schedule_text = ""
44 | for now_follow_date_index in range(len(daily_schedule_list)):
45 | daily_schedule_text += "☑" if daily_schedule_list[now_follow_date_index]['state'] else "☐"
46 | daily_schedule_text += daily_schedule_list[now_follow_date_index]['task'] + "\n"
47 | if daily_schedule_text.endswith("\n"):
48 | daily_schedule_text = daily_schedule_text[:-1]
49 | self.daily_trigger.emit(str(daily_schedule_text))
50 | time.sleep(2)
51 | except Exception:
52 | traceback.print_exc()
53 |
--------------------------------------------------------------------------------
/util/winreg_util.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import win32com.client # 需要安装 pywin32
4 |
5 |
6 | def get_exe_path():
7 | """获取正确的可执行文件路径"""
8 | if getattr(sys, 'frozen', False):
9 | # 打包环境:使用sys.executable
10 | return sys.executable
11 | else:
12 | # 开发环境:使用当前脚本路径
13 | return os.path.abspath(sys.argv[0])
14 |
15 |
16 | def get_startup_folder():
17 | """获取启动文件夹路径"""
18 | return os.path.join(os.environ['APPDATA'],
19 | r'Microsoft\Windows\Start Menu\Programs\Startup')
20 |
21 |
22 | def get_shortcut_path():
23 | """获取快捷方式路径"""
24 | return os.path.join(get_startup_folder(), "七仔的桌面工具.lnk")
25 |
26 |
27 | def is_auto_start_enabled():
28 | """检查是否已启用自启动"""
29 | shortcut_path = get_shortcut_path()
30 | if not os.path.exists(shortcut_path):
31 | return False
32 | try:
33 | # 检查快捷方式指向的路径是否正确
34 | shell = win32com.client.Dispatch("WScript.Shell")
35 | shortcut = shell.CreateShortCut(shortcut_path)
36 | current_path = get_exe_path()
37 | return os.path.normpath(shortcut.Targetpath) == os.path.normpath(current_path)
38 | except Exception as e:
39 | print(f"Error checking shortcut: {e}")
40 | return False
41 |
42 |
43 | def set_auto_start(enabled):
44 | """启用/禁用自启动"""
45 | shortcut_path = get_shortcut_path()
46 | if enabled:
47 | try:
48 | # 获取当前可执行文件路径
49 | target_path = get_exe_path()
50 | # 获取工作目录
51 | working_dir = os.path.dirname(target_path)
52 |
53 | # 确保启动文件夹存在
54 | startup_folder = get_startup_folder()
55 | if not os.path.exists(startup_folder):
56 | os.makedirs(startup_folder)
57 |
58 | # 创建快捷方式
59 | shell = win32com.client.Dispatch("WScript.Shell")
60 | shortcut = shell.CreateShortCut(shortcut_path)
61 | shortcut.Targetpath = target_path
62 | shortcut.WorkingDirectory = working_dir
63 | shortcut.save()
64 | print(f"Created shortcut at: {shortcut_path}")
65 | except Exception as e:
66 | print(f"Error creating shortcut: {e}")
67 | else:
68 | try:
69 | # 删除快捷方式
70 | if os.path.exists(shortcut_path):
71 | os.remove(shortcut_path)
72 | print(f"Removed shortcut: {shortcut_path}")
73 | except Exception as e:
74 | print(f"Error removing shortcut: {e}")
--------------------------------------------------------------------------------
/util/time_util.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | """
4 | name: 日期时间工具
5 | by: baby7
6 | blog: https://www.baby7blog.com
7 | annotation: 日期时间工具
8 | """
9 | import time
10 | import cnlunar
11 | import datetime
12 | from zhdate import ZhDate
13 |
14 |
15 | def get_datetime_str(in_datetime=datetime.datetime.now()):
16 | """
17 | 获取当前日期时间的字符串
18 | :param in_datetime: 时间
19 | """
20 | return str(in_datetime.strftime("%Y-%m-%d %H:%M:%S"))
21 |
22 |
23 | def get_date_str(in_datetime=datetime.datetime.today()):
24 | """
25 | 获取当前日期的字符串
26 | :param in_datetime: 日期
27 | """
28 | return str(in_datetime.strftime("%Y-%m-%d"))
29 |
30 |
31 | def get_time_str(in_datetime=datetime.datetime.now()):
32 | """
33 | 获取当前时间的字符串
34 | :param in_datetime: 时间
35 | """
36 | return str(in_datetime.strftime("%H:%M:%S"))
37 |
38 |
39 | def get_week_str(in_datetime=datetime.datetime.today()):
40 | """
41 | 获取当前周几的字符串
42 | :param in_datetime: 日期
43 | """
44 | return f"星期{list('一二三四五六日')[in_datetime.weekday()]}"
45 |
46 |
47 | def get_chinese_date_str(in_datetime=datetime.datetime.today()):
48 | """
49 | 获取当前日期时间的字符串
50 | :param in_datetime: 日期
51 | """
52 | return str(in_datetime.strftime("%Y年%m月%d日"))
53 |
54 |
55 | def get_lunar_calendar_str(in_datetime=datetime.datetime.today()):
56 | """
57 | 返回农历字符串
58 | :param in_datetime: 日期
59 | :return: 例如: 癸卯兔年 农历正月十四
60 | """
61 | date4 = ZhDate.from_datetime(in_datetime)
62 | str_long = str(date4.chinese())[5:].replace("年 (", "").replace(")", "")
63 | return str_long.split(" ")[1] + " 农历" + str_long.split(" ")[0]
64 |
65 |
66 | def get_constellation(in_datetime=datetime.datetime.today()):
67 | """
68 | 获取星座
69 | :param in_datetime: 日期
70 | :return: 例如:巨蟹座
71 | """
72 | constellation = ['魔羯', '水瓶', '双鱼', '牡羊', '金牛', '双子', '巨蟹', '狮子', '处女', '天秤', '天蝎', '射手']
73 | cutoff_days = (20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22)
74 | _month = in_datetime.month - (1 if in_datetime.day < cutoff_days[in_datetime.month - 1] else 0)
75 | _month = _month if _month < 12 else 0
76 | return constellation[_month] + "座"
77 |
78 |
79 | def get_week_by_year():
80 | """
81 | 获取这周是今年的第几周
82 | """
83 | return "第 " + str(int(time.strftime("%W")) + 1) + " 周"
84 |
85 |
86 | def get_holiday(in_datetime=datetime.datetime.today()):
87 | """
88 | 获取节气
89 | """
90 | return str(cnlunar.Lunar(in_datetime).todaySolarTerms).replace("无", "")
91 |
--------------------------------------------------------------------------------
/thread_list/start_module_list_thread.py:
--------------------------------------------------------------------------------
1 | # -- coding: utf-8 --
2 | import os
3 | import win32api
4 | import traceback
5 | from PySide2.QtCore import *
6 | from config import start_module_list_config
7 | from util import ip_change_util
8 |
9 |
10 | # 启动模块线程
11 | class StartModuleListThread(QThread):
12 |
13 | active = True # 线程是否需要保持执行
14 | error_trigger = Signal(str) # 错误触发器
15 | now_start_model_title = "尚未开始" # 当前启动的模块
16 |
17 | def __init__(self, parent=None):
18 | super().__init__(parent)
19 |
20 | def stop(self):
21 | self.terminate()
22 |
23 | """
24 | {
25 | start_module_list": [
26 | {
27 | "name": "ip_change",
28 | "type": "custom",
29 | "title": "host自动适应",
30 | "sort": 1
31 | },
32 | {
33 | "name": "AirLiveDrive",
34 | "type": "program",
35 | "title": "打开AirLiveDrive",
36 | "path": "E:\\soft\\AirLiveDrive\\AirLiveDrive.exe",
37 | "hide": 0,
38 | "sort": 2
39 | },
40 | {
41 | "name": "Clash",
42 | "type": "program",
43 | "title": "打开Clash",
44 | "path": "E:\\soft\\Clash for Windows\\Clash for Windows.exe",
45 | "hide": 0,
46 | "sort": 3
47 | }
48 | ]
49 | }
50 | """
51 | def run(self):
52 | start_module_list = start_module_list_config.get_start_module_list_config()['start_module_list']
53 | for start_module in start_module_list:
54 | if not self.active:
55 | break
56 | self.now_start_model_title = start_module['title']
57 | print("执行" + self.now_start_model_title)
58 | try:
59 | # 特定的 - host自适应
60 | if start_module['name'] == "ip_change":
61 | ip_change_util.change()
62 | continue
63 | # 打开程序
64 | if start_module['type'] == "program":
65 | search_list = os.popen('tasklist | findstr ' + str(start_module['name'])).readlines()
66 | if search_list is not None and len(search_list) > 0:
67 | print("程序 " + self.now_start_model_title + " 已在运行,跳过")
68 | continue
69 | win32api.ShellExecute(0, 'open', start_module['path'], '', '', int(start_module['hide']))
70 | continue
71 | except Exception:
72 | self.error_trigger.emit(self.now_start_model_title)
73 | traceback.print_exc()
74 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
98 | __pypackages__/
99 |
100 | # Celery stuff
101 | celerybeat-schedule
102 | celerybeat.pid
103 |
104 | # SageMath parsed files
105 | *.sage.py
106 |
107 | # Environments
108 | .env
109 | .venv
110 | env/
111 | venv/
112 | ENV/
113 | env.bak/
114 | venv.bak/
115 |
116 | # Spyder project settings
117 | .spyderproject
118 | .spyproject
119 |
120 | # Rope project settings
121 | .ropeproject
122 |
123 | # mkdocs documentation
124 | /site
125 |
126 | # mypy
127 | .mypy_cache/
128 | .dmypy.json
129 | dmypy.json
130 |
131 | # Pyre type checker
132 | .pyre/
133 |
134 | # pytype static type analyzer
135 | .pytype/
136 |
137 | # Cython debug symbols
138 | cython_debug/
139 |
140 | *.json
141 |
142 | /out
--------------------------------------------------------------------------------
/record_form.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'record_form.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.15.4
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 | from PySide2 import QtCore, QtGui, QtWidgets
12 |
13 |
14 | class Ui_Form(object):
15 | def setupUi(self, Form):
16 | Form.setObjectName("Form")
17 | Form.resize(232, 461)
18 | self.scroll_area = QtWidgets.QScrollArea(Form)
19 | self.scroll_area.setGeometry(QtCore.QRect(7, 32, 218, 421))
20 | font = QtGui.QFont()
21 | font.setFamily("思源黑体")
22 | self.scroll_area.setFont(font)
23 | self.scroll_area.setStyleSheet(" border-style: solid;\n"
24 | " border-radius: 10px;\n"
25 | " border: 1px groove gray;\n"
26 | " color: rgb(0, 0, 0);\n"
27 | " border-color: rgba(255, 255, 255, 1);\n"
28 | " background-color: rgba(255, 255, 255, 1);")
29 | self.scroll_area.setFrameShape(QtWidgets.QFrame.StyledPanel)
30 | self.scroll_area.setLineWidth(1)
31 | self.scroll_area.setWidgetResizable(True)
32 | self.scroll_area.setObjectName("scroll_area")
33 | self.scrollAreaWidgetContents = QtWidgets.QWidget()
34 | self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 216, 419))
35 | self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
36 | self.drink_table_view = QtWidgets.QTableView(self.scrollAreaWidgetContents)
37 | self.drink_table_view.setGeometry(QtCore.QRect(10, 20, 191, 391))
38 | self.drink_table_view.setObjectName("drink_table_view")
39 | self.scroll_area.setWidget(self.scrollAreaWidgetContents)
40 | self.push_button_60s_news = QtWidgets.QPushButton(Form)
41 | self.push_button_60s_news.setGeometry(QtCore.QRect(20, 5, 81, 35))
42 | font = QtGui.QFont()
43 | font.setFamily("思源黑体")
44 | font.setPointSize(11)
45 | self.push_button_60s_news.setFont(font)
46 | self.push_button_60s_news.setStyleSheet("QPushButton {\n"
47 | " border-style: solid;\n"
48 | " border-radius: 10px;\n"
49 | " color: #FFFFFF;\n"
50 | " border-color: #000000;\n"
51 | " background-color: rgba(0, 0, 0, 0.3);\n"
52 | "}")
53 | self.push_button_60s_news.setObjectName("push_button_60s_news")
54 | self.push_button_60s_news.raise_()
55 | self.scroll_area.raise_()
56 |
57 | self.retranslateUi(Form)
58 | QtCore.QMetaObject.connectSlotsByName(Form)
59 |
60 | def retranslateUi(self, Form):
61 | _translate = QtCore.QCoreApplication.translate
62 | Form.setWindowTitle(_translate("Form", "Form"))
63 | self.push_button_60s_news.setText(_translate("Form", "喝水记录"))
64 |
--------------------------------------------------------------------------------
/record_form.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 232
10 | 461
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 7
20 | 32
21 | 218
22 | 421
23 |
24 |
25 |
26 |
27 | 思源黑体
28 |
29 |
30 |
31 | border-style: solid;
32 | border-radius: 10px;
33 | border: 1px groove gray;
34 | color: rgb(0, 0, 0);
35 | border-color: rgba(255, 255, 255, 1);
36 | background-color: rgba(255, 255, 255, 1);
37 |
38 |
39 | QFrame::StyledPanel
40 |
41 |
42 | 1
43 |
44 |
45 | true
46 |
47 |
48 |
49 |
50 | 0
51 | 0
52 | 216
53 | 419
54 |
55 |
56 |
57 |
58 |
59 | 10
60 | 20
61 | 191
62 | 391
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | 20
72 | 5
73 | 81
74 | 35
75 |
76 |
77 |
78 |
79 | 思源黑体
80 | 11
81 |
82 |
83 |
84 | QPushButton {
85 | border-style: solid;
86 | border-radius: 10px;
87 | color: #FFFFFF;
88 | border-color: #000000;
89 | background-color: rgba(0, 0, 0, 0.3);
90 | }
91 |
92 |
93 | 喝水记录
94 |
95 |
96 | push_button_60s_news
97 | scroll_area
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/setting.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 |
3 | from PySide2 import QtCore
4 | from PySide2.QtCore import Signal
5 | from PySide2.QtWidgets import QMessageBox
6 | from qframelesswindow import AcrylicWindow
7 |
8 | from setting_form import Ui_Form
9 | import config.drinking_setting as drinking_setting
10 |
11 |
12 | class SettingWindow(AcrylicWindow, Ui_Form):
13 |
14 | setting_signal = Signal(str)
15 |
16 | def __init__(self, parent=None, use_parent=None):
17 | super(SettingWindow, self).__init__(parent=parent)
18 |
19 | self.setupUi(self)
20 | self.setWindowFlag(QtCore.Qt.Tool)
21 |
22 | self.use_parent = use_parent
23 | # 设置标题栏
24 | self.setWindowTitle("七仔的桌面工具 - 喝水设置")
25 | self.titleBar.minBtn.close()
26 | self.titleBar.maxBtn.close()
27 | drink_config = drinking_setting.get_drinking_setting()
28 | self.spin_box_drinking_count.setValue(int(drink_config['drinking_count']))
29 | view_message = drink_config['view_message']
30 | view_message_str = "正着计数" if view_message == "positive" else "倒着计数"
31 | self.combo_box_view_message.setCurrentText(view_message_str)
32 | qssStyle = '''
33 | QComboBox {
34 | color: black;
35 | border-radius: 3px;
36 | border: 1px groove gray;
37 | color: rgb(0, 0, 0);
38 | border-color: rgb(0, 0, 0);
39 | background-color: rgb(255, 255, 255);
40 | }
41 | '''
42 | self.combo_box_view_message.setStyleSheet(qssStyle)
43 |
44 | def push_button_ok_click(self):
45 | view_message_str = self.combo_box_view_message.itemText(self.combo_box_view_message.currentIndex())
46 | view_message = "positive" if view_message_str == "正着计数" else "negative"
47 | drink_config = {
48 | "drinking_count": int(self.spin_box_drinking_count.text()), # 喝水数量
49 | "view_message": view_message, # 窗口信息 正着计数(positive)/倒着计数(negative)
50 | }
51 | drinking_setting.set_drinking_setting(drink_config)
52 | self.setting_signal.emit('success')
53 | self.box_info("成功", "喝水设置成功")
54 |
55 | def box_info(self, title, message):
56 | msg_box = QMessageBox(self.use_parent)
57 | msg_box.setWindowTitle(title)
58 | msg_box.setText(message)
59 | # 设置背景色为白色,字体颜色为黑色
60 | msg_box.setStyleSheet(
61 | "QMessageBox { background-color: white; }"
62 | "QLabel { color: black; }"
63 | "QPushButton { border-radius: 10px; border: 1px groove black; padding: 5px; }"
64 | "QPushButton:hover { border: 1px groove blue; }"
65 | )
66 | # 创建自定义中文按钮
67 | ok_button = msg_box.addButton("确认", QMessageBox.RejectRole)
68 | msg_box.setDefaultButton(ok_button)
69 | msg_box.exec_()
70 |
71 |
--------------------------------------------------------------------------------
/new_todo.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 | from PySide2 import QtCore
3 | from PySide2.QtCore import Signal, QDateTime
4 | from qframelesswindow import AcrylicWindow
5 |
6 | from new_todo_form import Ui_Form
7 |
8 |
9 | class NewTodoWindow(AcrylicWindow, Ui_Form):
10 |
11 | setting_signal = Signal(str)
12 |
13 | input_data = ["", "", False, "Third", False, "", ""]
14 | def __init__(self, parent=None, input_data=None):
15 | super(NewTodoWindow, self).__init__(parent=parent)
16 | self.input_data = ["", "", False, "First", False, "", ""]
17 | self.setupUi(self)
18 | self.setWindowFlag(QtCore.Qt.Tool)
19 | # 设置标题栏
20 | if input_data is not None:
21 | self.setWindowTitle("七仔的桌面工具 - 新建待办事项")
22 | else:
23 | self.setWindowTitle("七仔的桌面工具 - 编辑待办事项")
24 | self.titleBar.minBtn.close()
25 | self.titleBar.maxBtn.close()
26 | self.check_push_button.clicked.connect(self.todo_checked_click)
27 | self.push_button_cancel.clicked.connect(self.close)
28 | self.combo_box_degree.setCurrentText("莫慌")
29 | print(input_data)
30 | if input_data is not None:
31 | self.input_data = input_data
32 | self.line_edit_title.setText(input_data[1])
33 | self.text_edit_des.setText(input_data[6])
34 | if input_data[3] == "First":
35 | self.combo_box_degree.setCurrentText("紧急")
36 | elif input_data[3] == "Second":
37 | self.combo_box_degree.setCurrentText("一般")
38 | elif input_data[3] == "Third":
39 | self.combo_box_degree.setCurrentText("莫慌")
40 | if input_data[4]:
41 | self.check_push_button.setText("✓")
42 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 0px groove #000;\n"
43 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgba(0, 0, 0, 0.5);")
44 | else:
45 | self.check_push_button.setText("")
46 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 1px groove #000;\n"
47 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgb(255, 255, 255);")
48 | self.date_time_edit.setDateTime(QDateTime.fromString(input_data[5], 'yyyy-MM-dd hh:mm:ss'))
49 |
50 | def todo_checked_click(self):
51 | if self.check_push_button.text() == "":
52 | self.check_push_button.setText("✓")
53 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 0px groove #000;\n"
54 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgba(0, 0, 0, 0.5);")
55 | else:
56 | self.check_push_button.setText("")
57 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 1px groove #000;\n"
58 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgb(255, 255, 255);")
59 |
--------------------------------------------------------------------------------
/util/resolution_util.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | """
4 | name: 动画和分辨率工具
5 | by: baby7
6 | blog: https://www.baby7blog.com
7 | annotation: 分辨率参数初始化和动画执行
8 | """
9 | from win32api import GetMonitorInfo, MonitorFromPoint
10 | from PySide2.QtCore import QSequentialAnimationGroup, QPropertyAnimation, QRect, QEasingCurve
11 | from PySide2.QtWidgets import QApplication
12 |
13 |
14 | def init_resolution(main_window):
15 | """
16 | 初始化分辨率参数
17 | :param main_window: 主窗口
18 | """
19 | desktop = QApplication.desktop().screenGeometry(0) # 多显示屏,显示主屏
20 | main_window.desktop_width = desktop.width()
21 | main_window.desktop_height = desktop.height()
22 | # 屏幕信息
23 | monitor_info = GetMonitorInfo(MonitorFromPoint((0, 0)))
24 | monitor = monitor_info.get('Monitor') # 屏幕分辨率
25 | work = monitor_info.get('Work') # 工作区间
26 | # 缩放比例
27 | scaling = monitor[2] / main_window.desktop_width
28 | # 任务栏高度
29 | main_window.taskbar_height = int(int(monitor[3] - work[3]) / scaling)
30 |
31 |
32 | def in_animation(main_window):
33 | """
34 | 进入动画
35 | :param main_window: 主窗口
36 | :return:
37 | """
38 | # 从下到上
39 | # start_animation(
40 | # main_window,
41 | # main_window.desktop_width - main_window.width(),
42 | # main_window.desktop_height,
43 | # main_window.desktop_width - main_window.width(),
44 | # main_window.desktop_height - main_window.height() - main_window.taskbar_height,
45 | # )
46 | # 从右到左
47 | main_window.show_form = True
48 | start_animation(
49 | main_window,
50 | main_window.desktop_width,
51 | 0,
52 | main_window.desktop_width - main_window.width(),
53 | 0,
54 | )
55 |
56 |
57 | def out_animation(main_window):
58 | """
59 | 退出动画
60 | :param main_window: 主窗口
61 | :return:
62 | """
63 | # 从上到下
64 | # start_animation(
65 | # main_window,
66 | # main_window.desktop_width - main_window.width(),
67 | # main_window.desktop_height - main_window.height() - main_window.taskbar_height,
68 | # main_window.desktop_width - main_window.width(),
69 | # main_window.desktop_height,
70 | # )
71 | # 从左到右
72 | main_window.show_form = False
73 | start_animation(
74 | main_window,
75 | main_window.desktop_width - main_window.width(),
76 | 0,
77 | main_window.desktop_width,
78 | 0,
79 | )
80 |
81 |
82 | def start_animation(main_window, start_x, start_y, end_x, end_y):
83 | """
84 | 动画执行
85 | :param main_window: 主窗口
86 | :param start_x: 初始点x
87 | :param start_y: 初始点y
88 | :param end_x: 结束点x
89 | :param end_y: 结束点y
90 | :return:
91 | """
92 | main_window.group = QSequentialAnimationGroup()
93 | animation = QPropertyAnimation(main_window, b'geometry')
94 | main_window.group.addAnimation(animation)
95 | animation.setDuration(200) # 持续时间
96 | animation.setStartValue(QRect(start_x, start_y, main_window.width(), main_window.height()))
97 | animation.setEndValue(QRect(end_x, end_y, main_window.width(), main_window.height()))
98 | # animation.setEasingCurve(QEasingCurve.OutBack) # 动画特效
99 | animation.setEasingCurve(QEasingCurve.Linear) # 动画特效
100 | main_window.group.start()
101 |
--------------------------------------------------------------------------------
/util/card_util.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets
2 | from PySide2.QtWidgets import *
3 | from PySide2 import QtCore, QtGui
4 |
5 |
6 | def set_card_location(card, sort, top):
7 | # x = 206
8 | x = 202
9 | y = top + int((int(sort / 2) - 1) * (12 + 71))
10 | if sort % 2 == 1:
11 | # x = 12
12 | x = 16
13 | y = top + int(int(sort / 2) * (12 + 71))
14 | card['title_label'].setText(card['title'])
15 | card['card_label'].setGeometry(QtCore.QRect(x, y, 181, 71))
16 | card['title_label'].setGeometry(QtCore.QRect(x + 8, y + 5, 161, 21))
17 | card['content_label'].setGeometry(QtCore.QRect(x + 8, y + 30, 161, 31))
18 |
19 |
20 | def get_load_info_card(form, card_list, info_config, info_object):
21 | for card in card_list:
22 | if card['type'] == "info" and card['name'] == info_config['card']['file_name']:
23 | return card
24 | # 背景label
25 | card_label = QtWidgets.QLabel(form)
26 | card_label.setGeometry(QtCore.QRect(0, 0, 0, 0))
27 | font = QtGui.QFont()
28 | font.setFamily("思源黑体")
29 | font.setPointSize(10)
30 | card_label.setFont(font)
31 | # card_label.setStyleSheet("border-style: solid;\n"
32 | # "border-radius: 10px;\n"
33 | # "border: 0px groove gray;\n"
34 | # "color: rgb(0, 0, 0);\n"
35 | # "border-color: rgba(100, 100, 100, 0);\n"
36 | # "background-color: rgba(255, 255, 255, 1);")
37 | card_label.setStyleSheet("border-style: solid;\n"
38 | "border-radius: 10px;\n"
39 | "border: 1px groove gray;\n"
40 | "color: rgb(0, 0, 0);\n"
41 | "border-color: rgba(0, 0, 0, 0.5);\n"
42 | "background-color: rgba(255, 255, 255, 1);")
43 | shadow = QGraphicsDropShadowEffect()
44 | shadow.setOffset(0, 0) # 偏移
45 | shadow.setBlurRadius(1) # 阴影半径
46 | # shadow.setColor(QtCore.Qt.white) # 阴影颜色
47 | shadow.setColor(QtCore.Qt.black) # 阴影颜色
48 | card_label.setGraphicsEffect(shadow)
49 | card_label.setText("")
50 | card_label.setAlignment(QtCore.Qt.AlignCenter)
51 | card_label.setObjectName("card_info_" + info_config['card']['file_name'])
52 | # 标题label
53 | title_label = QtWidgets.QLabel(form)
54 | title_label.setGeometry(QtCore.QRect(0, 0, 0, 0))
55 | font = QtGui.QFont()
56 | font.setFamily("思源黑体")
57 | font.setPointSize(10)
58 | title_label.setFont(font)
59 | title_label.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
60 | title_label.setObjectName("title_label_" + info_config['card']['file_name'])
61 | # 内容label
62 | content_label = QtWidgets.QLabel(form)
63 | content_label.setGeometry(QtCore.QRect(0, 0, 0, 0))
64 | content_label.setText("")
65 | content_label.setObjectName("content_label_" + info_config['card']['file_name'])
66 | card_list.append({
67 | "type": "info",
68 | "name": info_config['card']['file_name'],
69 | "title": info_config['card']['title'],
70 | "object": info_object(),
71 | "card_label": card_label,
72 | "title_label": title_label,
73 | "content_label": content_label
74 | })
75 | for card in card_list:
76 | if card['type'] == "info" and card['name'] == info_config['card']['file_name']:
77 | return card
78 |
--------------------------------------------------------------------------------
/module/drink_paint.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtCore, QtGui
2 | from PySide2.QtCore import *
3 | from PySide2.QtGui import *
4 |
5 |
6 | def paintEvent(main_object, event):
7 | left_x = 12
8 | top_y = 276
9 | # 绘制准备工作,启用反锯齿
10 | painter = QPainter(main_object)
11 | painter.setRenderHints(QtGui.QPainter.Antialiasing)
12 | painter.setPen(QtCore.Qt.NoPen)
13 | # 先画圆角矩形背景
14 | background_rect_gradient = QConicalGradient(50, 50, 91)
15 | background_rect_gradient.setColorAt(0, QColor(255, 255, 255, 240))
16 | background_rect_gradient.setColorAt(1, QColor(255, 255, 255, 240))
17 | rectPath = QPainterPath()
18 | rectPath.addRoundedRect(QRectF(left_x, top_y, 181 + 24, 154), 10, 10)
19 | painter.setBrush(background_rect_gradient)
20 | painter.setPen(QPen(background_rect_gradient, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
21 | painter.drawPath(rectPath)
22 | # 先画一个外圆
23 | background_arc_gradient = QConicalGradient(50, 50, 91)
24 | background_arc_gradient.setColorAt(0, QColor(main_object.line_color, main_object.line_color, main_object.line_color, 50))
25 | background_arc_gradient.setColorAt(1, QColor(main_object.line_color, main_object.line_color, main_object.line_color, 50))
26 | main_object.background_arc_pen = QPen()
27 | main_object.background_arc_pen.setBrush(background_arc_gradient) # 设置画刷渐变效果
28 | main_object.background_arc_pen.setWidth(5)
29 | main_object.background_arc_pen.setCapStyle(Qt.RoundCap)
30 | painter.setPen(main_object.background_arc_pen)
31 | painter.drawArc(QtCore.QRectF(30 + left_x + 12, 17 + top_y, 120, 120), 0, 360*16) # 画外圆
32 | # 再画一个内圆
33 | gradient = QConicalGradient(50, 50, 91)
34 | gradient.setColorAt(0, QColor(main_object.text_color))
35 | gradient.setColorAt(1, QColor(main_object.text_color))
36 | main_object.pen = QPen()
37 | main_object.pen.setBrush(gradient) # 设置画刷渐变效果
38 | main_object.pen.setWidth(5)
39 | main_object.pen.setCapStyle(Qt.RoundCap)
40 | painter.setPen(main_object.pen)
41 | rotate_angle = 360 * main_object.schedule / main_object.drinking_count
42 | painter.drawArc(QtCore.QRectF(30 + left_x + 12, 17 + top_y, 120, 120), (90 - 0) * 16, int(-rotate_angle * 16)) # 画圆环
43 | # 提示文字
44 | font = QtGui.QFont()
45 | font.setFamily("思源黑体")
46 | font.setPointSize(11)
47 | font.setBold(False)
48 | painter.setFont(font)
49 | painter.setPen(QColor(main_object.text_color))
50 | if main_object.view_message == "positive":
51 | # 显示进度条当前进度(正着数)
52 | painter.drawText(QtCore.QRectF(left_x + 12, top_y, 181, 154),
53 | Qt.AlignCenter, "今天第%d杯水" % main_object.schedule)
54 | else:
55 | if int(main_object.drinking_count - main_object.schedule) > 0:
56 | # 显示进度条当前进度(倒着数)
57 | painter.drawText(QtCore.QRectF(left_x + 12, top_y, 181, 154),
58 | Qt.AlignCenter, "还有%d杯水" % int(main_object.drinking_count - main_object.schedule))
59 | elif int(main_object.drinking_count - main_object.schedule) == 0:
60 | # 显示进度条当前进度(倒着数)
61 | painter.drawText(QtCore.QRectF(left_x + 12, top_y, 181, 154),
62 | Qt.AlignCenter, "%d杯水目标完成" % int(main_object.drinking_count))
63 | else:
64 | # 显示进度条当前进度(正着数)
65 | painter.drawText(QtCore.QRectF(left_x + 12, top_y, 181, 154),
66 | Qt.AlignCenter, "今天第%d杯水" % main_object.schedule)
67 | # 画图完成,更新
68 | main_object.update()
69 |
--------------------------------------------------------------------------------
/util/ip_change_util.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | """
4 | name: 根据本机ip决定是否做域名映射
5 | by: baby7
6 | blog: https://www.baby7blog.com
7 | annotation: 解决内网无法访问本宽带公网ip的问题
8 | """
9 | import socket
10 |
11 |
12 | LAN_IP_1 = "192.168.4." # 局域网固定ip(网线)
13 | DNS_1 = "192.168.4.1 myself.baby7blog.com" # 域名解析(网线)
14 | ANNOTATION_DNS_1 = "#192.168.4.1 myself.baby7blog.com" # 注释掉的域名解析(网线)
15 |
16 | LAN_IP_2 = "192.168.3." # 局域网固定ip(wifi)
17 | DNS_2 = "192.168.3.79 myself.baby7blog.com" # 域名解析(wifi)
18 | ANNOTATION_DNS_2 = "#192.168.3.79 myself.baby7blog.com" # 注释掉的域名解析(wifi)
19 |
20 | HOST_PATH = r'C:\Windows\System32\drivers\etc\hosts' # hosts文件地址
21 |
22 |
23 | def change():
24 | """
25 | 修改IP(自家用)
26 | """
27 | print("===================================开始host自动适应===================================")
28 | # 获取当前本机IP
29 | # ip = socket.gethostbyname(socket.gethostname())
30 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
31 | s.connect(("8.8.8.8", 80))
32 | ip = s.getsockname()[0]
33 | print("当前ip为:" + str(ip))
34 | # 局域网需要做域名映射到内网ip
35 | file = open(HOST_PATH, "r+", encoding='utf-8')
36 | lines = file.readlines()
37 | line_192_168_4_1 = str(lines[0])
38 | line_192_168_3_79 = str(lines[1])
39 | edit_tag = False
40 | if LAN_IP_1 in str(ip):
41 | lines[0] = line_192_168_4_1.replace(ANNOTATION_DNS_1, DNS_1)
42 | if lines[0] != line_192_168_4_1:
43 | edit_tag = True
44 | if "#" not in line_192_168_3_79:
45 | lines[1] = line_192_168_3_79.replace(DNS_2, ANNOTATION_DNS_2)
46 | if lines[1] != line_192_168_3_79:
47 | edit_tag = True
48 | if not edit_tag:
49 | print("不需要修改host")
50 | print("===================================host自动适应完成===================================")
51 | return
52 | fo = open(HOST_PATH, "r+", encoding='utf-8')
53 | fo.writelines(lines)
54 | elif LAN_IP_2 in str(ip):
55 | if "#" not in line_192_168_4_1:
56 | lines[0] = line_192_168_4_1.replace(DNS_1, ANNOTATION_DNS_1)
57 | if lines[0] != line_192_168_4_1:
58 | edit_tag = True
59 | lines[1] = line_192_168_3_79.replace(ANNOTATION_DNS_2, DNS_2)
60 | if lines[1] != line_192_168_3_79:
61 | edit_tag = True
62 | if not edit_tag:
63 | print("不需要修改host")
64 | print("===================================host自动适应完成===================================")
65 | return
66 | fo = open(HOST_PATH, "r+", encoding='utf-8')
67 | fo.writelines(lines)
68 | else:
69 | if "#" not in line_192_168_4_1:
70 | lines[0] = line_192_168_4_1.replace(DNS_1, ANNOTATION_DNS_1)
71 | if lines[0] != line_192_168_4_1:
72 | print(lines[0])
73 | print(line_192_168_4_1)
74 | edit_tag = True
75 | if "#" not in line_192_168_3_79:
76 | lines[1] = line_192_168_3_79.replace(DNS_2, ANNOTATION_DNS_2)
77 | if lines[1] != line_192_168_3_79:
78 | print(lines[1])
79 | print(line_192_168_3_79)
80 | edit_tag = True
81 | if not edit_tag:
82 | print("不需要修改host")
83 | print("===================================host自动适应完成===================================")
84 | return
85 | fo = open(HOST_PATH, "r+", encoding='utf-8')
86 | fo.writelines(lines)
87 | print("===================================host自动适应完成===================================")
88 |
--------------------------------------------------------------------------------
/module/click_connect.py:
--------------------------------------------------------------------------------
1 | from functools import partial
2 |
3 |
4 | def click_connect(main_object):
5 | # 绑定卡片按钮
6 | main_object.push_button_60s_news.clicked.connect(main_object.push_button_60s_click)
7 | main_object.push_button_weibo_info.clicked.connect(main_object.push_button_weibo_click)
8 | main_object.push_button_looking.clicked.connect(main_object.push_button_looking_click)
9 | main_object.push_button_reading.clicked.connect(main_object.push_button_reading_click)
10 | main_object.push_button_todo.clicked.connect(main_object.push_button_todo_click)
11 | # 城市选择
12 | main_object.weather_position_label.clicked.connect(main_object.open_city_view)
13 | # 新增待办事项
14 | main_object.push_button_todo_add.clicked.connect(partial(main_object.open_new_todo_view, None))
15 | # 热搜选项按钮
16 | main_object.push_button_top_weibo.clicked.connect(main_object.push_button_top_weibo_click)
17 | main_object.push_button_top_baidu.clicked.connect(main_object.push_button_top_baidu_click)
18 | main_object.push_button_top_bilibili.clicked.connect(main_object.push_button_top_bilibili_click)
19 | main_object.push_button_top_zhihu.clicked.connect(main_object.push_button_top_zhihu_click)
20 | main_object.push_button_top_douyin.clicked.connect(main_object.push_button_top_douyin_click)
21 | main_object.push_button_top_tencent.clicked.connect(main_object.push_button_top_tencent_click)
22 | main_object.push_button_top_refresh.clicked.connect(main_object.push_button_top_refresh_click)
23 | # 待办事项按钮
24 | main_object.push_button_todo_todo.clicked.connect(main_object.push_button_todo_open_click)
25 | main_object.push_button_todo_ok.clicked.connect(main_object.push_button_todo_close_click)
26 | # Looking卡片按钮绑定
27 | main_object.push_button_looking_fish.clicked.connect(main_object.push_button_looking_fish_click)
28 | main_object.push_button_looking_everyday.clicked.connect(main_object.push_button_looking_everyday_click)
29 | # main_object.push_button_looking_girl_animation.clicked.connect(main_object.push_button_looking_girl_animation_click)
30 | # main_object.push_button_looking_girl_real.clicked.connect(main_object.push_button_looking_girl_real_click)
31 | # Reading卡片按钮绑定
32 | main_object.push_button_reading_history.clicked.connect(main_object.push_button_reading_history_click)
33 | main_object.push_button_reading_life.clicked.connect(main_object.push_button_reading_life_click)
34 | main_object.push_button_reading_riddle.clicked.connect(main_object.push_button_reading_riddle_click)
35 | main_object.push_button_reading_rainbow.clicked.connect(main_object.push_button_reading_rainbow_click)
36 | main_object.push_button_reading_morning.clicked.connect(main_object.push_button_reading_morning_click)
37 | main_object.push_button_reading_night.clicked.connect(main_object.push_button_reading_night_click)
38 | main_object.push_button_reading_chicken_1.clicked.connect(main_object.push_button_reading_chicken_1_click)
39 | main_object.push_button_reading_chicken_2.clicked.connect(main_object.push_button_reading_chicken_2_click)
40 | main_object.push_button_reading_cheesy_love.clicked.connect(main_object.push_button_reading_cheesy_love_click)
41 | # 喝水绑定
42 | main_object.label_add.clicked.connect(main_object.push_button_add_click)
43 | main_object.push_button_restart.clicked.connect(main_object.push_button_clear_click)
44 | main_object.push_button_drinking_setting.clicked.connect(main_object.open_drinking_setting_view)
45 | main_object.push_button_drinking_history.clicked.connect(main_object.open_drinking_record_view)
46 | # 开机启动
47 | main_object.push_button_auto_start.clicked.connect(main_object.push_button_auto_start_click)
48 | # 退出
49 | main_object.push_button_exit.clicked.connect(main_object.quit_before)
--------------------------------------------------------------------------------
/module/init_module.py:
--------------------------------------------------------------------------------
1 | # 基础包
2 | import os
3 | import logging
4 | from PySide2 import QtCore, QtGui
5 | from PySide2.QtCore import *
6 | from PySide2.QtWidgets import QGraphicsDropShadowEffect
7 |
8 | # 工具
9 | from util import resolution_util
10 |
11 | # 模块
12 | from module import click_connect, update_info
13 |
14 | # 初始化日志
15 | import util.logger as logger
16 |
17 | def init_module(main_object):
18 | # 初始化日志
19 | config_path = str(os.getcwd()) + r"\log.log"
20 | main_object.info_logger = logger.Logger(config_path, logging.ERROR, logging.DEBUG)
21 | main_object.info_logger.info(main_object.app_name + "启动中...")
22 | # 隐藏部分
23 | # main_object.weibo_text_browser.hide()
24 | main_object.top_area.hide()
25 | main_object.scroll_area.hide()
26 | main_object.looking_area.hide()
27 | main_object.reading_area.hide()
28 | main_object.todo_area.hide()
29 | # main_object.weibo_text_browser.setGeometry(QtCore.QRect(20, 500 - 55, 361, 520 + 15))
30 | main_object.top_area.setGeometry(QtCore.QRect(12, 440, 381, 581))
31 | main_object.todo_area.setGeometry(QtCore.QRect(12, 440, 381, 581))
32 | main_object.scroll_area.setGeometry(QtCore.QRect(12, 440, 381, 581))
33 | main_object.looking_area.setGeometry(QtCore.QRect(18, 440, 364, 581))
34 | main_object.reading_area.setGeometry(QtCore.QRect(18, 440, 364, 581))
35 | # 开始线程
36 | main_object.start_thread_list()
37 | main_object.info_logger.info(main_object.app_name + "线程启动完成")
38 | # 更新日期部分
39 | main_object.update_date_and_time_model(True)
40 | # 更新天气部分
41 | main_object.weather_black_image = QtGui.QPixmap(":img/weather/black80.png")
42 | main_object.weather_blue_image = QtGui.QPixmap(":img/weather/blue80.png")
43 | # main_object.weather_blue_image = QtGui.QPixmap(":img/weather/lightBlue80.png")
44 | main_object.weather_list = [
45 | {"image": main_object.weather_image_label_1, "info": main_object.weather_info_label_1, 'temp': main_object.weather_temp_label_1},
46 | {"image": main_object.weather_image_label_2, "info": main_object.weather_info_label_2, 'temp': main_object.weather_temp_label_2},
47 | {"image": main_object.weather_image_label_3, "info": main_object.weather_info_label_3, 'temp': main_object.weather_temp_label_3},
48 | {"image": main_object.weather_image_label_4, "info": main_object.weather_info_label_4, 'temp': main_object.weather_temp_label_4},
49 | {"image": main_object.weather_image_label_5, "info": main_object.weather_info_label_5, 'temp': main_object.weather_temp_label_5}
50 | ]
51 | main_object.update_weather_info()
52 | # 更新倒计时部分
53 | main_object.update_count_down_list_by_api()
54 | # 绑定按钮
55 | click_connect.click_connect(main_object)
56 | # 退出动画
57 | resolution_util.out_animation(main_object)
58 | label_list = [
59 | main_object.label,
60 | main_object.label_2,
61 | main_object.label_5,
62 | main_object.push_button_schedule,
63 | # main_object.push_button_60s_news,
64 | # main_object.push_button_weibo_info
65 | ]
66 | for label in label_list:
67 | shadow1 = QGraphicsDropShadowEffect()
68 | shadow1.setOffset(0, 0) # 偏移
69 | shadow1.setBlurRadius(5) # 阴影半径
70 | shadow1.setColor(QtCore.Qt.white) # 阴影颜色
71 | label.setGraphicsEffect(shadow1)
72 | # 设置浏览器不打开链接
73 | main_object.weibo_text_browser.setOpenLinks(False)
74 | main_object.weibo_text_browser.setOpenExternalLinks(False)
75 | main_object.weibo_text_browser.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
76 | main_object.weibo_text_browser.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
77 | main_object.info_logger.info(main_object.app_name + "启动完成")
78 | # 喝水初始化
79 | main_object.init_config()
80 | update_info.check_v(main_object)
--------------------------------------------------------------------------------
/get_info/get_tophub_blog_info.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | """
4 | name: 获取信息
5 | by: baby7
6 | blog: https://www.baby7blog.com
7 | annotation: 获取信息
8 | """
9 | import time
10 | import random
11 | import requests
12 | from lxml import etree
13 |
14 |
15 | def get_base_info():
16 | try:
17 | # 输出时间戳
18 | now_timestamp = int(time.time() * 1000)
19 | sina_global = str(int(random.random() * 10000000000000)) + "." + str(int(random.random() * 10000)) \
20 | + "." + str(now_timestamp - 14 - 1072340 - 6)
21 | apache = str(int(random.random() * 10000000000000)) + "." + str(int(random.random() * 10000)) \
22 | + "." + str(now_timestamp - 14)
23 | ulv = str(now_timestamp) + ":2:2:2:" \
24 | + str(int(random.random() * 10000000000000)) + "." + str(int(random.random() * 10000)) \
25 | + "." + str(now_timestamp - 14) \
26 | + ":" + str(now_timestamp - 14 - 1072340)
27 | cookie_result = 'SUB=_2AkMUqfltf8NxqwJRmPEVz2Pib4V_zwrEieKi9Qi2JRMxHRl-yT9kqk0ttRB6PynXgT5CUZzGwlh-mIyUQvhe-_yXXtj3; ' + \
28 | 'SUBP=0033WrSXqPxfM72-Ws9jqgMF55529P9D9WFyRDSrne6a4e.bkQHJzd-.; ' + \
29 | 'SINAGLOBAL=' + sina_global + '; _s_tentry=-; ' + \
30 | 'Apache=' + apache + '; ' + \
31 | 'ULV=' + ulv
32 | # 请求头
33 | header = {
34 | 'cookie': cookie_result,
35 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.50',
36 | }
37 | res = requests.get(url="https://tophub.today", headers=header, timeout=3)
38 | return res
39 | except Exception as e:
40 | print("Error:{0}".format(e))
41 | return {"text": "403 Forbidden"}
42 |
43 |
44 | # 处理成可以展示的html
45 | def change_style(res, type_name, logger):
46 | try:
47 | if "403 Forbidden" in str(res.text):
48 | return "Login"
49 | result = '
| 序号 | 关键词 | |
'
50 | html = etree.HTML(res.text) # 转化成html文件
51 | if type_name == "baidu":
52 | search_list = html.xpath('//div[@id="node-2"]/div/div[2]/div[1]/a')
53 | elif type_name == "bilibili":
54 | search_list = html.xpath('//div[@id="node-19"]/div/div[2]/div[1]/a')
55 | elif type_name == "zhihu":
56 | search_list = html.xpath('//div[@id="node-6"]/div/div[2]/div[1]/a')
57 | elif type_name == "douyin":
58 | search_list = html.xpath('//div[@id="node-221"]/div/div[2]/div[1]/a')
59 | elif type_name == "tencent":
60 | search_list = html.xpath('//div[@id="node-35059"]/div/div[2]/div[1]/a')
61 | else:
62 | return
63 | for search_item in search_list:
64 | # 热搜排名
65 | search_item_index = str(search_item.xpath(".//div/span[1]/text()")[0])
66 | # 热搜标题
67 | search_item_title = str(search_item.xpath(".//div/span[2]/text()")[0])
68 | # 热搜地址
69 | search_item_url = str(search_item.xpath("./@href")[0])
70 | # 热搜火爆度
71 | search_item_count = str(search_item.xpath(".//div/span[3]/text()")[0])
72 | # 组合数据
73 | result = result + '| ' + search_item_index + ' | '
74 | result = result + '' + search_item_title + ''
75 | result = result + ' ' + search_item_count + ' |
'
76 | result = result + '
'
77 | return result
78 | except Exception as e:
79 | print("Error:{0}".format(e))
80 | logger.info("获取热搜错误:{0}".format(e))
81 | return ""
82 |
--------------------------------------------------------------------------------
/util/count_down_util.py:
--------------------------------------------------------------------------------
1 | from datetime import timedelta, date
2 | import requests
3 | import datetime
4 |
5 |
6 | def get_day_of_day(n=0):
7 | '''''
8 | if n>=0,date is larger than today
9 | if n<0,date is less than today
10 | date format = "YYYY-MM-DD"
11 | '''
12 | if (n < 0):
13 | n = abs(n)
14 | return str(date.today() - timedelta(days=n))
15 | else:
16 | return str(date.today() + timedelta(days=n))
17 |
18 |
19 | def holiday_data_list():
20 | date_list_str = (get_day_of_day(0)
21 | + "," + get_day_of_day(1)
22 | + "," + get_day_of_day(2)
23 | + "," + get_day_of_day(3)
24 | + "," + get_day_of_day(4)
25 | + "," + get_day_of_day(5))
26 | header = {
27 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.50',
28 | }
29 | holiday_data_result = requests.get(
30 | 'https://api.qqsuu.cn/api/dm-jiejiari?date=' + date_list_str, headers=header).json()
31 | holiday_data_list = holiday_data_result['data']['list']
32 | holiday_list = []
33 | today = True
34 | for holiday_data in holiday_data_list:
35 | if today:
36 | holiday_list.append('今天: ' + holiday_data['date'] + ' ' + holiday_data['info'])
37 | today = False
38 | else:
39 | holiday_list.append(holiday_data['cnweekday'].replace("星期", "周") + ': '
40 | + holiday_data['date']
41 | + ' ' + holiday_data['info'].replace("调休日", "调休(补班)"))
42 | return holiday_list
43 |
44 |
45 | def holiday_data_list_timo():
46 | date_list_str = (get_day_of_day(0)
47 | + "," + get_day_of_day(1)
48 | + "," + get_day_of_day(2)
49 | + "," + get_day_of_day(3)
50 | + "," + get_day_of_day(4)
51 | + "," + get_day_of_day(5))
52 | header = {
53 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.50',
54 | }
55 | holiday_data_result = requests.get(
56 | 'https://timor.tech/api/holiday/batch?d=' + date_list_str + '&type=Y', headers=header).json()
57 | holiday_data_map = holiday_data_result['type']
58 | holiday_list = []
59 | today = True
60 | for holiday_data_index in range(len(holiday_data_map)):
61 | date_name = get_day_of_day(holiday_data_index)
62 | if today:
63 | if str(holiday_data_map[date_name]['type']) == "0":
64 | holiday_list.append('今天: 工作日')
65 | elif str(holiday_data_map[date_name]['type']) == "1":
66 | holiday_list.append('今天: 周末')
67 | elif str(holiday_data_map[date_name]['type']) == "2":
68 | holiday_list.append('今天: 节日')
69 | else:
70 | holiday_list.append('今天: 调休(补班)')
71 | today = False
72 | else:
73 | if str(holiday_data_map[date_name]['type']) == "0":
74 | holiday_list.append(holiday_data_map[date_name]['name'] + ': 工作日')
75 | elif str(holiday_data_map[date_name]['type']) == "1":
76 | holiday_list.append(holiday_data_map[date_name]['name'] + ': 周末')
77 | elif str(holiday_data_map[date_name]['type']) == "2":
78 | holiday_list.append(holiday_data_map[date_name]['name'] + ': 节日')
79 | else:
80 | holiday_list.append(holiday_data_map[date_name]['name'] + ': 调休(补班)')
81 | return holiday_list
82 |
83 |
84 | def special_data_list(special_list_config):
85 | # 当天时间
86 | today_str = str(datetime.datetime.today().strftime("%Y-%m-%d"))
87 | today = datetime.datetime.strptime(today_str, '%Y-%m-%d')
88 | # 获取思源笔记日程列表
89 | schedule_list = special_list_config
90 | important_schedule_list = []
91 | for schedule_info in schedule_list:
92 | it_day = datetime.datetime.strptime(schedule_info['date'], '%Y-%m-%d')
93 | gap_day = (it_day - today).days
94 | # 筛序以后的数据
95 | if gap_day <= 0:
96 | continue
97 | schedule_info['gap_day'] = str(gap_day)
98 | important_schedule_list.append(schedule_info)
99 | important_schedule_list = sorted(important_schedule_list, key=lambda x: x['date'])
100 | return important_schedule_list
101 |
--------------------------------------------------------------------------------
/get_info/get_schedule_info.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os.path
3 | import datetime
4 |
5 |
6 | # 思源数据路径
7 | root_path = r"X:\docker\siyuan\data"
8 | # 日程路径
9 | schedule_path = r"\20230214175805-k88kujg"
10 |
11 |
12 | def get_schedule_list():
13 | """
14 | 获取思源笔记中的日程
15 | """
16 | schedule_info_list = []
17 | try:
18 | # 打开思源笔记日程文件路径
19 | root_dir = os.path.abspath(root_path + schedule_path)
20 | for parent, dir_names, filenames in os.walk(root_dir):
21 | for filename in filenames:
22 | # 构建每个文件的绝对路径
23 | schedule_file_path = os.path.join(parent, filename)
24 | if not schedule_file_path.endswith(".sy"):
25 | continue
26 | with open(schedule_file_path, 'r', encoding='utf-8') as f:
27 | # 读取json格式的文件
28 | schedule_file_data = json.load(f)
29 | f.close()
30 | # 提取标题
31 | title = schedule_file_data['Properties']['title']
32 | if "模板" in title or "月份" in title:
33 | continue
34 | one_day_list = []
35 | task_list = schedule_file_data['Children'][0]['Children']
36 | for task in task_list:
37 | if task['Children'][0]['Type'] == "NodeTaskListItemMarker" \
38 | and task['Children'][1]['Type'] == "NodeParagraph"\
39 | and len(task['Children'][1]['Children']) == 1:
40 |
41 | one_day_list.append({
42 | "type": "daily",
43 | "task": str(task['Children'][1]['Children'][0]['Data']),
44 | "state": True if "TaskListItemChecked" in task['Children'][0] else False
45 | })
46 | elif task['Children'][0]['Type'] == "NodeTaskListItemMarker" \
47 | and task['Children'][1]['Type'] == "NodeParagraph"\
48 | and len(task['Children'][1]['Children']) == 2:
49 | # print(task['Children'][1]['Children'][0]['TextMarkTextContent'])
50 | one_day_list.append({
51 | "type": "important",
52 | "task": str(task['Children'][1]['Children'][1]['Data']).replace("", ""),
53 | "state": True if "TaskListItemChecked" in task['Children'][0] else False
54 | })
55 | if len(one_day_list) == 0:
56 | continue
57 | schedule_info = {
58 | "date": title,
59 | "list": one_day_list
60 | }
61 | schedule_info_list.append(schedule_info)
62 | except Exception as e:
63 | print("获取思源笔记中的日程失败:")
64 | print(e)
65 | return schedule_info_list
66 |
67 |
68 | def get_important_schedule_list():
69 | """
70 | 获取思源笔记中的重要日程列表
71 | """
72 | # 当天时间
73 | today_str = str(datetime.datetime.today().strftime("%Y-%m-%d"))
74 | today = datetime.datetime.strptime(today_str, '%Y-%m-%d')
75 | # 获取思源笔记日程列表
76 | schedule_list = get_schedule_list()
77 | important_schedule_list = []
78 | for schedule_info in schedule_list:
79 | for schedule_info_item in schedule_info['list']:
80 | # 筛序重要的日程
81 | if schedule_info_item['type'] != "important":
82 | continue
83 | schedule_info_item['date'] = schedule_info['date']
84 | it_day = datetime.datetime.strptime(schedule_info_item['date'], '%Y-%m-%d')
85 | gap_day = (it_day - today).days
86 | # 筛序以后的数据
87 | if gap_day <= 0:
88 | continue
89 | schedule_info_item['gap_day'] = str(gap_day)
90 | important_schedule_list.append(schedule_info_item)
91 | important_schedule_list = sorted(important_schedule_list, key=lambda x: x['date'])
92 | return important_schedule_list
93 |
94 |
95 | def get_daily_schedule_list():
96 | """
97 | 获取思源笔记中的当天日程列表
98 | """
99 | # 当天时间
100 | today_str = str(datetime.datetime.today().strftime("%Y-%m-%d"))
101 | # 获取思源笔记日程列表
102 | schedule_list = get_schedule_list()
103 | important_schedule_list = []
104 | for schedule_info in schedule_list:
105 | for schedule_info_item in schedule_info['list']:
106 | schedule_info_item['date'] = schedule_info['date']
107 | if schedule_info_item['date'] != today_str:
108 | continue
109 | important_schedule_list.append(schedule_info_item)
110 | important_schedule_list = sorted(important_schedule_list, key=lambda x: x['date'])
111 | delete_item_count = 0
112 | delete_item_list = []
113 | if len(important_schedule_list) >= 7:
114 | for i in range(len(important_schedule_list)):
115 | if important_schedule_list[i]['state']:
116 | delete_item_count += 1
117 | delete_item_list.append(important_schedule_list[i])
118 | if delete_item_count >= (len(important_schedule_list) - 7):
119 | break
120 | for delete_item in delete_item_list:
121 | important_schedule_list.remove(delete_item)
122 | return important_schedule_list
123 |
--------------------------------------------------------------------------------
/city.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 | from PySide2 import QtCore
3 | from PySide2.QtCore import Signal
4 | from PySide2.QtWidgets import QMessageBox
5 | from qframelesswindow import AcrylicWindow
6 |
7 | import city_data
8 | from city_form import Ui_Form
9 | import config.city_setting as city_setting
10 |
11 |
12 | class CityWindow(AcrylicWindow, Ui_Form):
13 |
14 | city_signal = Signal(str)
15 |
16 | city_message = city_data.city_message
17 |
18 | current_city_data = []
19 |
20 | current_province_code = None
21 | current_city_code = None
22 | current_county_code = None
23 |
24 | def __init__(self, parent=None, use_parent=None):
25 | super(CityWindow, self).__init__(parent=parent)
26 |
27 | self.setupUi(self)
28 | self.setWindowFlag(QtCore.Qt.Tool)
29 | qssStyle = '''
30 | QComboBox {
31 | color: black;
32 | border-radius: 3px;
33 | border: 1px groove gray;
34 | color: rgb(0, 0, 0);
35 | border-color: rgb(0, 0, 0);
36 | background-color: rgb(255, 255, 255);
37 | }
38 | '''
39 | self.use_parent = use_parent
40 | # 设置标题栏
41 | self.setWindowTitle("七仔的桌面工具 - 天气城市设置")
42 | self.titleBar.minBtn.close()
43 | self.titleBar.maxBtn.close()
44 | self.combo_box_province.addItem("--请选择省")
45 | self.combo_box_province.setStyleSheet(qssStyle)
46 | self.combo_box_city.addItem("--请选择市")
47 | self.combo_box_city.setStyleSheet(qssStyle)
48 | self.combo_box_county.addItem("--请选择县/区")
49 | self.combo_box_county.setStyleSheet(qssStyle)
50 | for data in self.city_message['CityCode']:
51 | self.combo_box_province.addItem(data['provinceName'])
52 |
53 | # 省选择器点击响应
54 | def slot_province_click(self, text):
55 | current_province = self.combo_box_province.currentText()
56 | if current_province.startswith('--') is True or current_province == "":
57 | print("请选择省")
58 | self.combo_box_city.clear()
59 | self.combo_box_county.clear()
60 | return
61 | print("选择的省为:" + current_province)
62 | for data in self.city_message['CityCode']:
63 | if data['provinceName'] != current_province:
64 | continue
65 | print("开始填充市选择器")
66 | self.current_province_code = data['provinceCode']
67 | self.combo_box_city.clear()
68 | self.current_city_data = data['cityList']
69 | city_count = 0
70 | for c in data['cityList']:
71 | self.combo_box_city.addItem(c['cityName'])
72 | city_count += 1
73 | print(f"市选择器填充完成,数量:{city_count}")
74 |
75 | # 市选择器点击响应
76 | def slot_city_click(self, text):
77 | current_city = self.combo_box_city.currentText()
78 | if current_city.startswith('--') is True or current_city == "":
79 | print("请选择市")
80 | self.combo_box_county.clear()
81 | return
82 | print("选择的市为:" + current_city)
83 | for data in self.current_city_data:
84 | if data['cityName'] != current_city:
85 | continue
86 | print("开始填充区/县选择器")
87 | self.current_city_code = data['cityCode']
88 | self.combo_box_county.clear()
89 | county_count = 0
90 | for c in data['countyList']:
91 | self.combo_box_county.addItem(c['name'])
92 | county_count += 1
93 | print(f"区/县选择器填充完成,数量:{county_count}")
94 |
95 | def push_button_ok_click(self):
96 | current_county = self.combo_box_county.currentText()
97 | current_county_code = None
98 | current_county_Name = None
99 | for data in self.city_message['CityCode']:
100 | if data['provinceCode'] == self.current_province_code:
101 | for c in data['cityList']:
102 | if c['cityCode'] == self.current_city_code:
103 | for cc in c['countyList']:
104 | if cc['name'] == current_county:
105 | current_county_code = cc['code']
106 | current_county_Name = cc['name']
107 | if current_county_code is None:
108 | self.box_error("失败", "请选择正确的省市区")
109 | return
110 | city_setting.set_city_setting({
111 | 'province': self.current_province_code,
112 | 'city': self.current_city_code,
113 | 'county': current_county_code,
114 | 'countyName': current_county_Name
115 | })
116 | self.city_signal.emit('success')
117 | self.box_info("成功", "城市设置成功,会在十分钟内刷新,或重启刷新")
118 | return
119 |
120 | def box_info(self, title, message):
121 | msg_box = QMessageBox(self.use_parent)
122 | msg_box.setWindowTitle(title)
123 | msg_box.setText(message)
124 | # 设置背景色为白色,字体颜色为黑色
125 | msg_box.setStyleSheet(
126 | "QMessageBox { background-color: white; }"
127 | "QLabel { color: black; }"
128 | "QPushButton { border-radius: 10px; border: 1px groove black; padding: 5px; }"
129 | "QPushButton:hover { border: 1px groove blue; }"
130 | )
131 | # 创建自定义中文按钮
132 | ok_button = msg_box.addButton("确认", QMessageBox.RejectRole)
133 | msg_box.setDefaultButton(ok_button)
134 | msg_box.exec_()
135 |
136 | def box_error(self, title, message):
137 | msg_box = QMessageBox(self.use_parent)
138 | msg_box.setWindowTitle(title)
139 | msg_box.setText(message)
140 | # 设置背景色为白色,字体颜色为黑色
141 | msg_box.setStyleSheet(
142 | "QMessageBox { background-color: white; }"
143 | "QLabel { color: black; }"
144 | "QPushButton { border-radius: 10px; border: 1px groove black; padding: 5px; }"
145 | "QPushButton:hover { border: 1px groove blue; }"
146 | )
147 | # 创建自定义中文按钮
148 | ok_button = msg_box.addButton("确认", QMessageBox.RejectRole)
149 | msg_box.setDefaultButton(ok_button)
150 | msg_box.exec_()
151 |
--------------------------------------------------------------------------------
/module/update_info.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import webbrowser
3 |
4 | from PySide2.QtWidgets import QMessageBox
5 |
6 | import util.send_win_message_util as send_message_util
7 | from PySide2.QtCore import *
8 |
9 | # 工具
10 | from util import \
11 | time_util, \
12 | count_down_util
13 |
14 | # 配置
15 | from config import drinking_config
16 |
17 | # 获取信息
18 | from get_info import get_weather_info
19 |
20 | def update_weather_info(main_object, city_code):
21 | try:
22 | weather_info_list = get_weather_info.get_weather_info(city_code)
23 | days = len(main_object.weather_list)
24 | for i in range(days):
25 | weather_message = weather_info_list[i]['weather']
26 | if "雨" in weather_message:
27 | weather_image = get_weather_info.get_weather_image(weather_info_list[i], main_object.weather_blue_image)
28 | else:
29 | weather_image = get_weather_info.get_weather_image(weather_info_list[i], main_object.weather_black_image)
30 | main_object.weather_list[i]['image'].setPixmap(weather_image)
31 | if i == 0:
32 | weather_info = "今天 " + weather_message
33 | else:
34 | weather_info = weather_info_list[i]['date'] + " " + weather_message
35 | if i == 0:
36 | main_object.weather_list[i]['info'].setText(weather_info)
37 | elif len(weather_info) >= 10 and i > 0:
38 | main_object.weather_list[i]['info'].setText(weather_info[0:int(len(weather_info) / 2) + 1] + "\n"
39 | + weather_info[int(len(weather_info) / 2) + 1:])
40 | else:
41 | main_object.weather_list[i]['info'].setText(weather_info_list[i]['date'] + "\n"
42 | + weather_message)
43 | main_object.weather_list[i]['temp'].setText(weather_info_list[i]['temp'])
44 | main_object.info_logger.info("天气更新完成")
45 | except Exception as e:
46 | print("Error:{}".format(e))
47 |
48 |
49 | def update_date_and_time_model(main_object, update_time):
50 | """
51 | # 更新日期部分
52 | """
53 | today = datetime.datetime.today()
54 | main_object.info_logger.info(str(today.strftime("%Y年%m月%d日")))
55 | main_object.date_label.setText(time_util.get_chinese_date_str(today) + " "
56 | + time_util.get_week_str(today) + "\n"
57 | + time_util.get_lunar_calendar_str(today) + "\n"
58 | + time_util.get_constellation(today) + " "
59 | + time_util.get_week_by_year() + " "
60 | + time_util.get_holiday(today))
61 | if not update_time:
62 | return
63 | # 动态显示时间在label上
64 | main_object.timer = QTimer(main_object)
65 | # main_object.timer.setTimerType(Qt.PreciseTimer)
66 | main_object.timer.setInterval(100)
67 | main_object.timer.timeout.connect(main_object.showtime)
68 | main_object.timer.start()
69 |
70 |
71 | def update_count_down_list_by_api(main_object):
72 | """
73 | 基于接口的倒计时天数
74 | """
75 | try:
76 | holiday_list = count_down_util.holiday_data_list_timo()
77 | holiday_list_str = "\n".join(holiday_list[1:])
78 | main_object.daily_schedule_today.setText(holiday_list[0])
79 | main_object.daily_schedule_label.setText(holiday_list_str)
80 | main_object.info_logger.info("倒计时更新完成")
81 | except Exception as e:
82 | main_object.info_logger.error("{}".format(e))
83 |
84 |
85 | def time_trigger_update(main_object, datetime_now_str):
86 | """
87 | 定时刷新
88 | """
89 | try:
90 | print(datetime_now_str)
91 | datetime_now = datetime.datetime.strptime(datetime_now_str, "%Y-%m-%d %H:%M:%S")
92 | # 发送清单通知
93 | for open_todo_data in main_object.open_todo_data_list:
94 | if open_todo_data[4] and open_todo_data[5] == datetime_now_str:
95 | send_message_util.send_message(main_object.app_name, "待办清单任务通知", open_todo_data[1])
96 | for close_todo_data in main_object.close_todo_data_list:
97 | if close_todo_data[4] and close_todo_data[5] == datetime_now_str:
98 | send_message_util.send_message(main_object.app_name, "已办清单任务通知", close_todo_data[1])
99 | # 记录日志
100 | main_object.info_logger.info("定时刷新")
101 | # 更新日期部分
102 | main_object.update_date_and_time_model(False)
103 | # 更新天气部分
104 | if int(datetime_now.minute) % 10 == 0:
105 | main_object.update_weather_info()
106 | # 更新倒计时部分(如果零点需要重置)
107 | if int(datetime_now.hour) == 0 and int(datetime_now.minute) == 0:
108 | main_object.update_count_down_list_by_api()
109 | # 更新喝水(如果零点需要重置)
110 | if int(datetime_now.hour) == 0 and int(datetime_now.minute) == 0:
111 | main_object.schedule = 0
112 | # 记录喝水数据
113 | drinking_config.set_drinking_config({
114 | "date": str(datetime.date.today().strftime("%Y-%m-%d")),
115 | "count": main_object.schedule
116 | })
117 | except Exception as e:
118 | main_object.info_logger.error("{}".format(e))
119 |
120 | def check_v(main_object):
121 | now = datetime.datetime.now()
122 | if now > datetime.datetime(2025, 9, 22):
123 | msg_box = QMessageBox(main_object)
124 | msg_box.setWindowTitle("七仔的桌面工具")
125 | msg_box.setText("有新版本,优化了各项操作,增加了多种功能,强烈建议您前往下载!")
126 | # 设置背景色为白色,字体颜色为黑色
127 | msg_box.setStyleSheet(
128 | "QMessageBox { background-color: white; }"
129 | "QLabel { color: black; }"
130 | "QPushButton { border-radius: 10px; border: 1px groove black; padding: 5px; }"
131 | "QPushButton:hover { border: 1px groove blue; }"
132 | )
133 | # 创建自定义中文按钮
134 | download_button = msg_box.addButton("前往下载", QMessageBox.RejectRole)
135 | later_button = msg_box.addButton("稍后提醒", QMessageBox.AcceptRole)
136 | msg_box.setDefaultButton(download_button)
137 | result = msg_box.exec_()
138 | if msg_box.clickedButton() == download_button:
139 | # 打开浏览器
140 | dl_start = "https"
141 | dl_name = "agiletiles"
142 | dl_domain = ".".join([dl_name, "lanzoue", "com"])
143 | webbrowser.open(f"{dl_start}://{dl_domain}/s/{dl_name}")
144 | main_object.quit_before()
145 | exit()
--------------------------------------------------------------------------------
/setting_form.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'setting_form.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.15.4
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 | from PySide2 import QtCore, QtGui, QtWidgets
12 |
13 |
14 | class Ui_Form(object):
15 | def setupUi(self, Form):
16 | Form.setObjectName("Form")
17 | Form.resize(237, 191)
18 | self.scroll_area = QtWidgets.QScrollArea(Form)
19 | self.scroll_area.setGeometry(QtCore.QRect(7, 32, 221, 151))
20 | font = QtGui.QFont()
21 | font.setFamily("思源黑体")
22 | self.scroll_area.setFont(font)
23 | self.scroll_area.setStyleSheet(" border-style: solid;\n"
24 | " border-radius: 10px;\n"
25 | " border: 1px groove gray;\n"
26 | " color: rgb(0, 0, 0);\n"
27 | " border-color: rgba(255, 255, 255, 1);\n"
28 | " background-color: rgba(255, 255, 255, 1);")
29 | self.scroll_area.setFrameShape(QtWidgets.QFrame.StyledPanel)
30 | self.scroll_area.setLineWidth(1)
31 | self.scroll_area.setWidgetResizable(True)
32 | self.scroll_area.setObjectName("scroll_area")
33 | self.scrollAreaWidgetContents = QtWidgets.QWidget()
34 | self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 219, 149))
35 | self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
36 | self.label_9 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
37 | self.label_9.setGeometry(QtCore.QRect(20, 60, 71, 21))
38 | font = QtGui.QFont()
39 | font.setFamily("思源黑体")
40 | font.setPointSize(11)
41 | self.label_9.setFont(font)
42 | self.label_9.setObjectName("label_9")
43 | self.spin_box_drinking_count = QtWidgets.QSpinBox(self.scrollAreaWidgetContents)
44 | self.spin_box_drinking_count.setGeometry(QtCore.QRect(90, 20, 41, 25))
45 | font = QtGui.QFont()
46 | font.setFamily("思源黑体")
47 | font.setPointSize(11)
48 | self.spin_box_drinking_count.setFont(font)
49 | self.spin_box_drinking_count.setStyleSheet(" border-style: solid;\n"
50 | " border-radius: 3px;\n"
51 | " border: 1px groove gray;\n"
52 | " color: rgb(0, 0, 0);\n"
53 | " border-color: rgb(0, 0, 0);\n"
54 | " background-color: rgb(255, 255, 255);")
55 | self.spin_box_drinking_count.setMinimum(1)
56 | self.spin_box_drinking_count.setMaximum(100)
57 | self.spin_box_drinking_count.setObjectName("spin_box_drinking_count")
58 | self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
59 | self.label.setGeometry(QtCore.QRect(31, 20, 61, 21))
60 | font = QtGui.QFont()
61 | font.setFamily("思源黑体")
62 | font.setPointSize(11)
63 | self.label.setFont(font)
64 | self.label.setObjectName("label")
65 | self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
66 | self.label_2.setGeometry(QtCore.QRect(134, 20, 41, 21))
67 | font = QtGui.QFont()
68 | font.setFamily("思源黑体")
69 | font.setPointSize(11)
70 | self.label_2.setFont(font)
71 | self.label_2.setObjectName("label_2")
72 | self.combo_box_view_message = QtWidgets.QComboBox(self.scrollAreaWidgetContents)
73 | self.combo_box_view_message.setGeometry(QtCore.QRect(100, 60, 91, 22))
74 | font = QtGui.QFont()
75 | font.setFamily("思源黑体")
76 | font.setPointSize(11)
77 | self.combo_box_view_message.setFont(font)
78 | self.combo_box_view_message.setStyleSheet(" border-style: solid;\n"
79 | " border-radius: 3px;\n"
80 | " border: 1px groove gray;\n"
81 | " color: rgb(0, 0, 0);\n"
82 | " border-color: rgb(0, 0, 0);\n"
83 | " background-color: rgb(255, 255, 255);")
84 | self.combo_box_view_message.setObjectName("combo_box_view_message")
85 | self.combo_box_view_message.addItem("")
86 | self.combo_box_view_message.addItem("")
87 | self.push_button_ok = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
88 | self.push_button_ok.setGeometry(QtCore.QRect(70, 100, 71, 23))
89 | font = QtGui.QFont()
90 | font.setFamily("思源黑体")
91 | font.setPointSize(10)
92 | self.push_button_ok.setFont(font)
93 | self.push_button_ok.setStyleSheet("QPushButton {\n"
94 | " border-style: solid;\n"
95 | " border-radius: 10px;\n"
96 | " border: 0px groove gray;\n"
97 | " color: #FFFFFF;\n"
98 | " border-color: #000000;\n"
99 | " background-color: rgba(0, 0, 0, 0.3);\n"
100 | "}\n"
101 | "QPushButton:hover {\n"
102 | " background: rgba(255, 255, 255, 0.5);\n"
103 | " color: rgb(0, 0, 0);\n"
104 | " border: 1px groove gray;\n"
105 | "}")
106 | self.push_button_ok.setObjectName("push_button_ok")
107 | self.label_9.raise_()
108 | self.label.raise_()
109 | self.label_2.raise_()
110 | self.combo_box_view_message.raise_()
111 | self.push_button_ok.raise_()
112 | self.spin_box_drinking_count.raise_()
113 | self.scroll_area.setWidget(self.scrollAreaWidgetContents)
114 | self.push_button_60s_news = QtWidgets.QPushButton(Form)
115 | self.push_button_60s_news.setGeometry(QtCore.QRect(20, 5, 81, 35))
116 | font = QtGui.QFont()
117 | font.setFamily("思源黑体")
118 | font.setPointSize(11)
119 | self.push_button_60s_news.setFont(font)
120 | self.push_button_60s_news.setStyleSheet("QPushButton {\n"
121 | " border-style: solid;\n"
122 | " border-radius: 10px;\n"
123 | " color: #FFFFFF;\n"
124 | " border-color: #000000;\n"
125 | " background-color: rgba(0, 0, 0, 0.3);\n"
126 | "}")
127 | self.push_button_60s_news.setObjectName("push_button_60s_news")
128 | self.push_button_60s_news.raise_()
129 | self.scroll_area.raise_()
130 |
131 | self.retranslateUi(Form)
132 | self.push_button_ok.clicked.connect(Form.push_button_ok_click)
133 | QtCore.QMetaObject.connectSlotsByName(Form)
134 |
135 | def retranslateUi(self, Form):
136 | _translate = QtCore.QCoreApplication.translate
137 | Form.setWindowTitle(_translate("Form", "Form"))
138 | self.label_9.setText(_translate("Form", "界面显示:"))
139 | self.label.setText(_translate("Form", "我要喝"))
140 | self.label_2.setText(_translate("Form", "杯水"))
141 | self.combo_box_view_message.setItemText(0, _translate("Form", "正着计数"))
142 | self.combo_box_view_message.setItemText(1, _translate("Form", "倒着计数"))
143 | self.push_button_ok.setText(_translate("Form", "确定"))
144 | self.push_button_60s_news.setText(_translate("Form", "喝水设置"))
145 |
--------------------------------------------------------------------------------
/util/style_util.py:
--------------------------------------------------------------------------------
1 | '''
2 | **********************************热搜 · 开始***************************************
3 | ↓ ↓
4 | '''
5 | top_open_style = """QPushButton {
6 | border-radius: 0px;
7 | background: rgb(255, 255, 255);
8 | border-bottom-left-radius: 4px;
9 | border-bottom-right-radius: 4px;
10 | border-style: solid;
11 | border: 2px solid #MAIN_COLOR;
12 | border-top-color: #ffffff;
13 | border-bottom-color: #MAIN_COLOR;
14 | border-left-color: #MAIN_COLOR;
15 | border-right-color: #MAIN_COLOR;
16 | border-bottom-left-radius: 10px;
17 | border-bottom-right-radius: 10px;
18 | }
19 | """
20 |
21 | top_close_style = """QPushButton {
22 | background: rgb(255, 255, 255);
23 | border-bottom-color: rgb(255, 255, 255);
24 | border-bottom-left-radius: 4px;
25 | border-bottom-right-radius: 4px;
26 | }
27 | QPushButton:hover {
28 | color: #TEXT_COLOR;
29 | }
30 | """
31 |
32 | top_line_style = """ color: #MAIN_COLOR;
33 | border-color: #MAIN_COLOR;
34 | background-color: #MAIN_COLOR;"""
35 |
36 | top_weibo_text_color = "#FF8D16"
37 | top_baidu_text_color = "#306eff"
38 | top_bilibili_text_color = "#F58CAB"
39 | top_zhihu_text_color = "#00a3ff"
40 | top_douyin_text_color = "#ff1752"
41 | top_tencent_text_color = "#fedc1c"
42 | top_weibo_color = "#000"
43 | top_baidu_color = "#000"
44 | top_bilibili_color = "#000"
45 | top_zhihu_color = "#000"
46 | top_douyin_color = "#000"
47 | top_tencent_color = "#000"
48 |
49 |
50 | def get_top_style(tab, state):
51 | if tab == "weibo" and state:
52 | return top_open_style.replace("#MAIN_COLOR", top_weibo_color).replace("#TEXT_COLOR", top_weibo_text_color)
53 | if tab == "weibo" and not state:
54 | return top_close_style.replace("#MAIN_COLOR", top_weibo_color).replace("#TEXT_COLOR", top_weibo_text_color)
55 | if tab == "baidu" and state:
56 | return top_open_style.replace("#MAIN_COLOR", top_baidu_color).replace("#TEXT_COLOR", top_baidu_text_color)
57 | if tab == "baidu" and not state:
58 | return top_close_style.replace("#MAIN_COLOR", top_baidu_color).replace("#TEXT_COLOR", top_baidu_text_color)
59 | if tab == "bilibili" and state:
60 | return top_open_style.replace("#MAIN_COLOR", top_bilibili_color).replace("#TEXT_COLOR", top_bilibili_text_color)
61 | if tab == "bilibili" and not state:
62 | return top_close_style.replace("#MAIN_COLOR", top_bilibili_color).replace("#TEXT_COLOR", top_bilibili_text_color)
63 | if tab == "zhihu" and state:
64 | return top_open_style.replace("#MAIN_COLOR", top_zhihu_color).replace("#TEXT_COLOR", top_zhihu_text_color)
65 | if tab == "zhihu" and not state:
66 | return top_close_style.replace("#MAIN_COLOR", top_zhihu_color).replace("#TEXT_COLOR", top_zhihu_text_color)
67 | if tab == "douyin" and state:
68 | return top_open_style.replace("#MAIN_COLOR", top_douyin_color).replace("#TEXT_COLOR", top_douyin_text_color)
69 | if tab == "douyin" and not state:
70 | return top_close_style.replace("#MAIN_COLOR", top_douyin_color).replace("#TEXT_COLOR", top_douyin_text_color)
71 | if tab == "tencent" and state:
72 | return top_open_style.replace("#MAIN_COLOR", top_tencent_color).replace("#TEXT_COLOR", top_tencent_text_color)
73 | if tab == "tencent" and not state:
74 | return top_close_style.replace("#MAIN_COLOR", top_tencent_color).replace("#TEXT_COLOR", top_tencent_text_color)
75 | if tab == "todo" and state:
76 | return top_open_style.replace("#MAIN_COLOR", top_tencent_color).replace("#TEXT_COLOR", top_weibo_text_color)
77 | if tab == "todo" and not state:
78 | return top_close_style.replace("#MAIN_COLOR", top_tencent_color).replace("#TEXT_COLOR", top_weibo_text_color)
79 | if tab == "success" and state:
80 | return top_open_style.replace("#MAIN_COLOR", top_tencent_color).replace("#TEXT_COLOR", top_zhihu_text_color)
81 | if tab == "success" and not state:
82 | return top_close_style.replace("#MAIN_COLOR", top_tencent_color).replace("#TEXT_COLOR", top_zhihu_text_color)
83 |
84 |
85 | def get_top_line_style(tab):
86 | if tab == "weibo":
87 | return top_line_style.replace("#MAIN_COLOR", top_weibo_color)
88 | if tab == "baidu":
89 | return top_line_style.replace("#MAIN_COLOR", top_baidu_color)
90 | if tab == "bilibili":
91 | return top_line_style.replace("#MAIN_COLOR", top_bilibili_color)
92 | if tab == "zhihu":
93 | return top_line_style.replace("#MAIN_COLOR", top_zhihu_color)
94 | if tab == "douyin":
95 | return top_line_style.replace("#MAIN_COLOR", top_douyin_color)
96 | if tab == "tencent":
97 | return top_line_style.replace("#MAIN_COLOR", top_tencent_color)
98 | if tab == "todo":
99 | return top_line_style.replace("#MAIN_COLOR", top_tencent_color)
100 | if tab == "success":
101 | return top_line_style.replace("#MAIN_COLOR", top_tencent_color)
102 | '''
103 | ↑ ↑
104 | **********************************热搜 · 结束***************************************
105 | '''
106 | '''
107 | **********************************菜单 · 开始***************************************
108 | ↓ ↓
109 | '''
110 | # menu_button_on = """ border-style: solid;
111 | # border-radius: 10px;
112 | # color: #FFFFFF;
113 | # border-color: #000000;
114 | # background-color: rgba(0, 0, 0, 0.3);
115 | # """
116 | # menu_button_off = """ border-style: solid;
117 | # border-radius: 10px;
118 | # border: 1px groove gray;
119 | # color: rgb(0, 0, 0);
120 | # border-color: rgba(0, 0, 0, 1);
121 | # background-color: rgba(255, 255, 255, 1);
122 | # """
123 | menu_button_on = """QPushButton {
124 | border-style: solid;
125 | border-radius: 10px;
126 | border: 0px groove gray;
127 | color: rgb(0, 0, 0);
128 | border-color: rgba(0, 0, 0, 1);
129 | background-color: rgba(255, 255, 255, 1);
130 | }
131 | """
132 | menu_button_off = """QPushButton {
133 | border-style: solid;
134 | border-radius: 10px;
135 | color: #FFFFFF;
136 | border-color: #000000;
137 | background-color: rgba(0, 0, 0, 0.3);
138 | }
139 | QPushButton:hover {
140 | background: rgba(255, 255, 255, 0.5);
141 | color: rgb(0, 0, 0);
142 | }
143 | """
144 |
145 |
146 | def get_menu_button_style(state):
147 | if state:
148 | return menu_button_on
149 | else:
150 | return menu_button_off
151 | '''
152 | ↑ ↑
153 | **********************************菜单 · 结束***************************************
154 | '''
--------------------------------------------------------------------------------
/city_form.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'city_form.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.15.11
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 | from PySide2 import QtCore, QtGui, QtWidgets
12 |
13 |
14 | class Ui_Form(object):
15 | def setupUi(self, Form):
16 | Form.setObjectName("Form")
17 | Form.resize(234, 248)
18 | self.scroll_area = QtWidgets.QScrollArea(Form)
19 | self.scroll_area.setGeometry(QtCore.QRect(7, 32, 218, 201))
20 | font = QtGui.QFont()
21 | font.setFamily("思源黑体")
22 | self.scroll_area.setFont(font)
23 | self.scroll_area.setStyleSheet(" border-style: solid;\n"
24 | " border-radius: 10px;\n"
25 | " border: 1px groove gray;\n"
26 | " color: rgb(0, 0, 0);\n"
27 | " border-color: rgba(255, 255, 255, 1);\n"
28 | " background-color: rgba(255, 255, 255, 1);")
29 | self.scroll_area.setFrameShape(QtWidgets.QFrame.StyledPanel)
30 | self.scroll_area.setLineWidth(1)
31 | self.scroll_area.setWidgetResizable(True)
32 | self.scroll_area.setObjectName("scroll_area")
33 | self.scrollAreaWidgetContents = QtWidgets.QWidget()
34 | self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 216, 199))
35 | self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
36 | self.label_13 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
37 | self.label_13.setGeometry(QtCore.QRect(20, 95, 61, 21))
38 | font = QtGui.QFont()
39 | font.setFamily("思源黑体")
40 | font.setPointSize(11)
41 | self.label_13.setFont(font)
42 | self.label_13.setObjectName("label_13")
43 | self.combo_box_county = QtWidgets.QComboBox(self.scrollAreaWidgetContents)
44 | self.combo_box_county.setGeometry(QtCore.QRect(82, 93, 111, 25))
45 | font = QtGui.QFont()
46 | font.setPointSize(12)
47 | self.combo_box_county.setFont(font)
48 | self.combo_box_county.setStyleSheet(" border-style: solid;\n"
49 | " border-radius: 3px;\n"
50 | " border: 1px groove gray;\n"
51 | " color: rgb(0, 0, 0);\n"
52 | " border-color: rgb(0, 0, 0);\n"
53 | " background-color: rgb(255, 255, 255);")
54 | self.combo_box_county.setObjectName("combo_box_county")
55 | self.combo_box_province = QtWidgets.QComboBox(self.scrollAreaWidgetContents)
56 | self.combo_box_province.setGeometry(QtCore.QRect(82, 13, 111, 25))
57 | font = QtGui.QFont()
58 | font.setPointSize(12)
59 | self.combo_box_province.setFont(font)
60 | self.combo_box_province.setStyleSheet(" border-style: solid;\n"
61 | " border-radius: 3px;\n"
62 | " border: 1px groove gray;\n"
63 | " color: rgb(0, 0, 0);\n"
64 | " border-color: rgb(0, 0, 0);\n"
65 | " background-color: rgb(255, 255, 255);")
66 | self.combo_box_province.setObjectName("combo_box_province")
67 | self.label_12 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
68 | self.label_12.setGeometry(QtCore.QRect(20, 55, 61, 21))
69 | font = QtGui.QFont()
70 | font.setFamily("思源黑体")
71 | font.setPointSize(11)
72 | self.label_12.setFont(font)
73 | self.label_12.setObjectName("label_12")
74 | self.push_button_ok = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
75 | self.push_button_ok.setGeometry(QtCore.QRect(70, 160, 61, 21))
76 | font = QtGui.QFont()
77 | font.setFamily("思源黑体")
78 | font.setPointSize(10)
79 | self.push_button_ok.setFont(font)
80 | self.push_button_ok.setStyleSheet("QPushButton {\n"
81 | " border-style: solid;\n"
82 | " border-radius: 10px;\n"
83 | " border: 0px groove gray;\n"
84 | " color: #FFFFFF;\n"
85 | " border-color: #000000;\n"
86 | " background-color: rgba(0, 0, 0, 0.3);\n"
87 | "}\n"
88 | "QPushButton:hover {\n"
89 | " background: rgba(255, 255, 255, 0.5);\n"
90 | " color: rgb(0, 0, 0);\n"
91 | " border: 1px groove gray;\n"
92 | "}")
93 | self.push_button_ok.setObjectName("push_button_ok")
94 | self.label_11 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
95 | self.label_11.setGeometry(QtCore.QRect(20, 15, 61, 21))
96 | font = QtGui.QFont()
97 | font.setFamily("思源黑体")
98 | font.setPointSize(11)
99 | self.label_11.setFont(font)
100 | self.label_11.setObjectName("label_11")
101 | self.combo_box_city = QtWidgets.QComboBox(self.scrollAreaWidgetContents)
102 | self.combo_box_city.setGeometry(QtCore.QRect(82, 53, 111, 25))
103 | font = QtGui.QFont()
104 | font.setPointSize(12)
105 | self.combo_box_city.setFont(font)
106 | self.combo_box_city.setStyleSheet(" border-style: solid;\n"
107 | " border-radius: 3px;\n"
108 | " border: 1px groove gray;\n"
109 | " color: rgb(0, 0, 0);\n"
110 | " border-color: rgb(0, 0, 0);\n"
111 | " background-color: rgb(255, 255, 255);")
112 | self.combo_box_city.setObjectName("combo_box_city")
113 | self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
114 | self.label.setGeometry(QtCore.QRect(10, 130, 191, 20))
115 | self.label.setAlignment(QtCore.Qt.AlignCenter)
116 | self.label.setObjectName("label")
117 | self.scroll_area.setWidget(self.scrollAreaWidgetContents)
118 | self.push_button_60s_news = QtWidgets.QPushButton(Form)
119 | self.push_button_60s_news.setGeometry(QtCore.QRect(20, 5, 81, 35))
120 | font = QtGui.QFont()
121 | font.setFamily("思源黑体")
122 | font.setPointSize(11)
123 | self.push_button_60s_news.setFont(font)
124 | self.push_button_60s_news.setStyleSheet("QPushButton {\n"
125 | " border-style: solid;\n"
126 | " border-radius: 10px;\n"
127 | " color: #FFFFFF;\n"
128 | " border-color: #000000;\n"
129 | " background-color: rgba(0, 0, 0, 0.3);\n"
130 | "}")
131 | self.push_button_60s_news.setObjectName("push_button_60s_news")
132 | self.push_button_60s_news.raise_()
133 | self.scroll_area.raise_()
134 |
135 | self.retranslateUi(Form)
136 | self.combo_box_province.currentTextChanged['QString'].connect(Form.slot_province_click) # type: ignore
137 | self.combo_box_city.currentTextChanged['QString'].connect(Form.slot_city_click) # type: ignore
138 | self.push_button_ok.clicked.connect(Form.push_button_ok_click) # type: ignore
139 | QtCore.QMetaObject.connectSlotsByName(Form)
140 |
141 | def retranslateUi(self, Form):
142 | _translate = QtCore.QCoreApplication.translate
143 | Form.setWindowTitle(_translate("Form", "Form"))
144 | self.label_13.setText(_translate("Form", "选择市:"))
145 | self.label_12.setText(_translate("Form", "选择市:"))
146 | self.push_button_ok.setText(_translate("Form", "确定"))
147 | self.label_11.setText(_translate("Form", "选择省:"))
148 | self.label.setText(_translate("Form", "如果选择出现问题请尝试重启软件"))
149 | self.push_button_60s_news.setText(_translate("Form", "选择城市"))
150 |
--------------------------------------------------------------------------------
/util/time_calculate.py:
--------------------------------------------------------------------------------
1 | import datetime
2 | import calendar
3 | import util.time_util
4 |
5 |
6 | def push_button_copy_now_today_click():
7 | now = datetime.datetime.now()
8 | zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
9 | microseconds=now.microsecond)
10 | return util.time_util.get_datetime_str(zero_today) + "," + util.time_util.get_datetime_str(now)
11 |
12 |
13 | def push_button_copy_now_15m_today_click():
14 | now = datetime.datetime.now()
15 | zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
16 | microseconds=now.microsecond)
17 | end_today = zero_today + datetime.timedelta(hours=now.hour, minutes=(int(now.minute/15) * 15), seconds=0,
18 | microseconds=now.microsecond)
19 | return util.time_util.get_datetime_str(zero_today) + "," + util.time_util.get_datetime_str(end_today)
20 |
21 |
22 | def push_button_copy_now_month_click(status):
23 | now = datetime.datetime.now()
24 | zero_month = datetime.datetime(now.year, now.month, 1)
25 | if status:
26 | zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second + 1,
27 | microseconds=now.microsecond)
28 | else:
29 | zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
30 | microseconds=now.microsecond)
31 | return util.time_util.get_datetime_str(zero_month) + "," + util.time_util.get_datetime_str(zero_today)
32 |
33 |
34 | def push_button_copy_now_year_click(status):
35 | now = datetime.datetime.now()
36 | zero_year = datetime.datetime(now.year, 1, 1)
37 | if status:
38 | zero_month = datetime.datetime(now.year, now.month, 1) - datetime.timedelta(microseconds=1)
39 | else:
40 | zero_month = datetime.datetime(now.year, now.month, 1)
41 | return util.time_util.get_datetime_str(zero_year) + "," + util.time_util.get_datetime_str(zero_month)
42 |
43 |
44 | def push_button_copy_today_click(status):
45 | now = datetime.datetime.now()
46 | zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second, microseconds=now.microsecond)
47 | if status:
48 | last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
49 | return util.time_util.get_datetime_str(zero_today) + "," + util.time_util.get_datetime_str(last_today)
50 | else:
51 | last_today = now - datetime.timedelta(days=-1, hours=now.hour, minutes=now.minute, seconds=now.second, microseconds=now.microsecond)
52 | return util.time_util.get_datetime_str(zero_today) + "," + util.time_util.get_datetime_str(last_today)
53 |
54 |
55 | def push_button_copy_yesterday_click(status):
56 | now = datetime.datetime.now()
57 | zero_today = now - datetime.timedelta(days=1, hours=now.hour, minutes=now.minute, seconds=now.second, microseconds=now.microsecond)
58 | if status:
59 | last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
60 | return util.time_util.get_datetime_str(zero_today) + "," + util.time_util.get_datetime_str(last_today)
61 | else:
62 | last_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second, microseconds=now.microsecond)
63 | return util.time_util.get_datetime_str(zero_today) + "," + util.time_util.get_datetime_str(last_today)
64 |
65 |
66 | def push_button_copy_current_month_click(status):
67 | now = datetime.datetime.now()
68 | zero_month = datetime.datetime(now.year, now.month, 1)
69 | if status:
70 | last_month = datetime.datetime(zero_month.year, zero_month.month,
71 | calendar.monthrange(zero_month.year, zero_month.month)[1], hour=23, minute=59, second=59)
72 | return util.time_util.get_datetime_str(zero_month) + "," + util.time_util.get_datetime_str(last_month)
73 | else:
74 | last_month = (datetime.datetime(zero_month.year, zero_month.month,
75 | calendar.monthrange(zero_month.year, zero_month.month)[1], hour=0, minute=0, second=0)
76 | + datetime.timedelta(hours=24, minutes=0, seconds=0))
77 | return util.time_util.get_datetime_str(zero_month) + "," + util.time_util.get_datetime_str(last_month)
78 |
79 |
80 | def push_button_copy_last_month_click(status):
81 | now = datetime.datetime.now()
82 | zero_month = datetime.datetime(now.year, now.month, 1) - datetime.timedelta(days=1)
83 | zero_month = datetime.datetime(zero_month.year, zero_month.month, 1)
84 | if status:
85 | last_month = datetime.datetime(zero_month.year, zero_month.month,
86 | calendar.monthrange(zero_month.year, zero_month.month)[1], hour=23, minute=59, second=59)
87 | return util.time_util.get_datetime_str(zero_month) + "," + util.time_util.get_datetime_str(last_month)
88 | else:
89 | last_month = (datetime.datetime(zero_month.year, zero_month.month,
90 | calendar.monthrange(zero_month.year, zero_month.month)[1], hour=0, minute=0, second=0)
91 | + datetime.timedelta(hours=24, minutes=0, seconds=0))
92 | return util.time_util.get_datetime_str(zero_month) + "," + util.time_util.get_datetime_str(last_month)
93 |
94 |
95 | def push_button_copy_current_year_click(status):
96 | now = datetime.datetime.now()
97 | zero_year = datetime.datetime(now.year, 1, 1)
98 | if status:
99 | last_year = datetime.datetime(zero_year.year, zero_year.month,
100 | calendar.monthrange(zero_year.year, zero_year.month)[1], hour=23, minute=59, second=59)
101 | return util.time_util.get_datetime_str(zero_year) + "," + util.time_util.get_datetime_str(last_year)
102 | else:
103 | last_year = (datetime.datetime(zero_year.year, zero_year.month,
104 | calendar.monthrange(zero_year.year, zero_year.month)[1], hour=0, minute=0, second=0)
105 | + datetime.timedelta(hours=24, minutes=0, seconds=0))
106 | return util.time_util.get_datetime_str(zero_year) + "," + util.time_util.get_datetime_str(last_year)
107 |
108 |
109 | def push_button_copy_last_year_click(status):
110 | now = datetime.datetime.now()
111 | zero_year = datetime.datetime(now.year - 1, 1, 1)
112 | if status:
113 | last_year = datetime.datetime(zero_year.year, zero_year.month,
114 | calendar.monthrange(zero_year.year, zero_year.month)[1], hour=23, minute=59, second=59)
115 | return util.time_util.get_datetime_str(zero_year) + "," + util.time_util.get_datetime_str(last_year)
116 | else:
117 | last_year = (datetime.datetime(zero_year.year, zero_year.month,
118 | calendar.monthrange(zero_year.year, zero_year.month)[1], hour=0, minute=0, second=0)
119 | + datetime.timedelta(hours=24, minutes=0, seconds=0))
120 | return util.time_util.get_datetime_str(zero_year) + "," + util.time_util.get_datetime_str(last_year)
--------------------------------------------------------------------------------
/setting_form.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 237
10 | 191
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 7
20 | 32
21 | 221
22 | 151
23 |
24 |
25 |
26 |
27 | 思源黑体
28 |
29 |
30 |
31 | border-style: solid;
32 | border-radius: 10px;
33 | border: 1px groove gray;
34 | color: rgb(0, 0, 0);
35 | border-color: rgba(255, 255, 255, 1);
36 | background-color: rgba(255, 255, 255, 1);
37 |
38 |
39 | QFrame::StyledPanel
40 |
41 |
42 | 1
43 |
44 |
45 | true
46 |
47 |
48 |
49 |
50 | 0
51 | 0
52 | 219
53 | 149
54 |
55 |
56 |
57 |
58 |
59 | 20
60 | 60
61 | 71
62 | 21
63 |
64 |
65 |
66 |
67 | 思源黑体
68 | 11
69 |
70 |
71 |
72 | 界面显示:
73 |
74 |
75 |
76 |
77 |
78 | 90
79 | 20
80 | 41
81 | 25
82 |
83 |
84 |
85 |
86 | 思源黑体
87 | 11
88 |
89 |
90 |
91 | border-style: solid;
92 | border-radius: 3px;
93 | border: 1px groove gray;
94 | color: rgb(0, 0, 0);
95 | border-color: rgb(0, 0, 0);
96 | background-color: rgb(255, 255, 255);
97 |
98 |
99 | 1
100 |
101 |
102 | 100
103 |
104 |
105 |
106 |
107 |
108 | 31
109 | 20
110 | 61
111 | 21
112 |
113 |
114 |
115 |
116 | 思源黑体
117 | 11
118 |
119 |
120 |
121 | 我要喝
122 |
123 |
124 |
125 |
126 |
127 | 134
128 | 20
129 | 41
130 | 21
131 |
132 |
133 |
134 |
135 | 思源黑体
136 | 11
137 |
138 |
139 |
140 | 杯水
141 |
142 |
143 |
144 |
145 |
146 | 100
147 | 60
148 | 91
149 | 22
150 |
151 |
152 |
153 |
154 | 思源黑体
155 | 11
156 |
157 |
158 |
159 | border-style: solid;
160 | border-radius: 3px;
161 | border: 1px groove gray;
162 | color: rgb(0, 0, 0);
163 | border-color: rgb(0, 0, 0);
164 | background-color: rgb(255, 255, 255);
165 |
166 | -
167 |
168 | 正着计数
169 |
170 |
171 | -
172 |
173 | 倒着计数
174 |
175 |
176 |
177 |
178 |
179 |
180 | 70
181 | 100
182 | 71
183 | 23
184 |
185 |
186 |
187 |
188 | 思源黑体
189 | 10
190 |
191 |
192 |
193 | QPushButton {
194 | border-style: solid;
195 | border-radius: 10px;
196 | border: 0px groove gray;
197 | color: #FFFFFF;
198 | border-color: #000000;
199 | background-color: rgba(0, 0, 0, 0.3);
200 | }
201 | QPushButton:hover {
202 | background: rgba(255, 255, 255, 0.5);
203 | color: rgb(0, 0, 0);
204 | border: 1px groove gray;
205 | }
206 |
207 |
208 | 确定
209 |
210 |
211 | label_9
212 | label
213 | label_2
214 | combo_box_view_message
215 | push_button_ok
216 | spin_box_drinking_count
217 |
218 |
219 |
220 |
221 |
222 | 20
223 | 5
224 | 81
225 | 35
226 |
227 |
228 |
229 |
230 | 思源黑体
231 | 11
232 |
233 |
234 |
235 | QPushButton {
236 | border-style: solid;
237 | border-radius: 10px;
238 | color: #FFFFFF;
239 | border-color: #000000;
240 | background-color: rgba(0, 0, 0, 0.3);
241 | }
242 |
243 |
244 | 喝水设置
245 |
246 |
247 | push_button_60s_news
248 | scroll_area
249 |
250 |
251 |
252 |
253 | push_button_ok
254 | clicked()
255 | Form
256 | push_button_ok_click()
257 |
258 |
259 | 89
260 | 364
261 |
262 |
263 | 25
264 | 297
265 |
266 |
267 |
268 |
269 |
270 | push_button_ok_click()
271 |
272 |
273 |
--------------------------------------------------------------------------------
/get_info/get_weather_info.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | """
4 | name: 获取天气信息
5 | by: baby7
6 | blog: https://www.baby7blog.com
7 | annotation: 来源地址: https://toy.lion1ou.tech/api/nowWeather 、 中国天气网
8 | """
9 | import datetime
10 |
11 | import requests
12 | from lxml import html
13 |
14 |
15 | weather_image_local_list = [
16 | {"name": "d0", "x": "0", "y": "0"},
17 | {"name": "d1", "x": "80", "y": "0"},
18 | {"name": "d2", "x": "160", "y": "0"},
19 | {"name": "d3", "x": "240", "y": "0"},
20 | {"name": "d4", "x": "320", "y": "0"},
21 | {"name": "d5", "x": "400", "y": "0"},
22 | {"name": "d6", "x": "480", "y": "0"},
23 | {"name": "d7", "x": "560", "y": "0"},
24 | {"name": "d8", "x": "640", "y": "0"},
25 | {"name": "d9", "x": "0", "y": "80"},
26 | {"name": "d00", "x": "0", "y": "0"},
27 | {"name": "d01", "x": "80", "y": "0"},
28 | {"name": "d02", "x": "160", "y": "0"},
29 | {"name": "d03", "x": "240", "y": "0"},
30 | {"name": "d04", "x": "320", "y": "0"},
31 | {"name": "d05", "x": "400", "y": "0"},
32 | {"name": "d06", "x": "480", "y": "0"},
33 | {"name": "d07", "x": "560", "y": "0"},
34 | {"name": "d08", "x": "640", "y": "0"},
35 | {"name": "d09", "x": "0", "y": "80"},
36 | {"name": "d10", "x": "80", "y": "80"},
37 | {"name": "d11", "x": "160", "y": "80"},
38 | {"name": "d12", "x": "240", "y": "80"},
39 | {"name": "d13", "x": "320", "y": "80"},
40 | {"name": "d14", "x": "400", "y": "80"},
41 | {"name": "d15", "x": "480", "y": "80"},
42 | {"name": "d16", "x": "560", "y": "80"},
43 | {"name": "d17", "x": "640", "y": "80"},
44 | {"name": "d18", "x": "0", "y": "160"},
45 | {"name": "d19", "x": "80", "y": "160"},
46 | {"name": "d20", "x": "160", "y": "160"},
47 | {"name": "d21", "x": "240", "y": "160"},
48 | {"name": "d22", "x": "320", "y": "160"},
49 | {"name": "d23", "x": "400", "y": "160"},
50 | {"name": "d24", "x": "480", "y": "160"},
51 | {"name": "d25", "x": "560", "y": "160"},
52 | {"name": "d26", "x": "640", "y": "160"},
53 | {"name": "d27", "x": "0", "y": "240"},
54 | {"name": "d28", "x": "80", "y": "240"},
55 | {"name": "d29", "x": "160", "y": "240"},
56 | {"name": "d30", "x": "240", "y": "240"},
57 | {"name": "d31", "x": "320", "y": "240"},
58 | {"name": "d32", "x": "400", "y": "240"},
59 | {"name": "d33", "x": "480", "y": "240"},
60 | {"name": "d53", "x": "560", "y": "240"},
61 | {"name": "d57", "x": "720", "y": "0"},
62 | {"name": "d32", "x": "720", "y": "80"},
63 | {"name": "d49", "x": "720", "y": "160"},
64 | {"name": "d58", "x": "720", "y": "240"},
65 | {"name": "d54", "x": "800", "y": "0"},
66 | {"name": "d55", "x": "800", "y": "80"},
67 | {"name": "d56", "x": "800", "y": "160"},
68 | {"name": "d301", "x": "880", "y": "0"},
69 | {"name": "d302", "x": "880", "y": "80"},
70 | {"name": "n0", "x": "0", "y": "320"},
71 | {"name": "n1", "x": "80", "y": "320"},
72 | {"name": "n2", "x": "160", "y": "320"},
73 | {"name": "n3", "x": "240", "y": "320"},
74 | {"name": "n4", "x": "320", "y": "320"},
75 | {"name": "n5", "x": "400", "y": "320"},
76 | {"name": "n6", "x": "480", "y": "320"},
77 | {"name": "n7", "x": "560", "y": "320"},
78 | {"name": "n8", "x": "640", "y": "320"},
79 | {"name": "n9", "x": "0", "y": "400"},
80 | {"name": "n00", "x": "0", "y": "320"},
81 | {"name": "n01", "x": "80", "y": "320"},
82 | {"name": "n02", "x": "160", "y": "320"},
83 | {"name": "n03", "x": "240", "y": "320"},
84 | {"name": "n04", "x": "320", "y": "320"},
85 | {"name": "n05", "x": "400", "y": "320"},
86 | {"name": "n06", "x": "480", "y": "320"},
87 | {"name": "n07", "x": "560", "y": "320"},
88 | {"name": "n08", "x": "640", "y": "320"},
89 | {"name": "n09", "x": "0", "y": "400"},
90 | {"name": "n10", "x": "80", "y": "400"},
91 | {"name": "n11", "x": "160", "y": "400"},
92 | {"name": "n12", "x": "240", "y": "400"},
93 | {"name": "n13", "x": "320", "y": "400"},
94 | {"name": "n14", "x": "400", "y": "400"},
95 | {"name": "n15", "x": "480", "y": "400"},
96 | {"name": "n16", "x": "560", "y": "400"},
97 | {"name": "n17", "x": "640", "y": "400"},
98 | {"name": "n18", "x": "0", "y": "480"},
99 | {"name": "n19", "x": "80", "y": "480"},
100 | {"name": "n20", "x": "160", "y": "480"},
101 | {"name": "n21", "x": "240", "y": "480"},
102 | {"name": "n22", "x": "320", "y": "480"},
103 | {"name": "n23", "x": "400", "y": "480"},
104 | {"name": "n24", "x": "480", "y": "480"},
105 | {"name": "n25", "x": "560", "y": "480"},
106 | {"name": "n26", "x": "640", "y": "480"},
107 | {"name": "n27", "x": "0", "y": "560"},
108 | {"name": "n28", "x": "80", "y": "560"},
109 | {"name": "n29", "x": "160", "y": "560"},
110 | {"name": "n30", "x": "240", "y": "560"},
111 | {"name": "n31", "x": "320", "y": "560"},
112 | {"name": "n32", "x": "400", "y": "560"},
113 | {"name": "n33", "x": "480", "y": "560"},
114 | {"name": "n53", "x": "560", "y": "560"},
115 | {"name": "n57", "x": "720", "y": "320"},
116 | {"name": "n32", "x": "720", "y": "400"},
117 | {"name": "n49", "x": "720", "y": "480"},
118 | {"name": "n58", "x": "720", "y": "560"},
119 | {"name": "n54", "x": "800", "y": "320"},
120 | {"name": "n55", "x": "800", "y": "400"},
121 | {"name": "n56", "x": "800", "y": "480"},
122 | {"name": "n301", "x": "880", "y": "320"}
123 | ]
124 |
125 |
126 | def get_easy_weather_info(city_code=330106):
127 | """
128 | 获取天气信息(toy.lion1ou.tech),简易版本
129 | :param city_code: 城市代码,西湖表示330106
130 | :return:
131 | """
132 | data = {
133 | "city": str(city_code)
134 | }
135 | weather_info = requests.post(url="https://toy.lion1ou.tech/api/nowWeather", data=data).json()
136 | return weather_info['data']
137 |
138 |
139 | def get_weather_info(city_code=101210101, days=6):
140 | """
141 | 获取中国天气网信息
142 | :param city_code:101210101
143 | :return:
144 | """
145 | weather_list = []
146 | try:
147 | hour = datetime.datetime.today().hour
148 | url = 'http://www.weather.com.cn/weather/%s.shtml' % city_code
149 | content = requests.get(url, timeout=2).content
150 | sel = html.fromstring(content)
151 | top_list = sel.xpath('//ul[@class="t clearfix"]')[0]
152 | for i in range(1, days + 1):
153 | date = top_list.xpath('li[%d]/h1/text()' % i)[0]
154 | weather = top_list.xpath('li[%d]/p[@class="wea"]/text()' % i)[0]
155 | image = str(top_list.xpath('//*[@id="7d"]/ul/li[%d]/big[2]/@class' % i)[0]).split(" ")[1]
156 | if hour < 17:
157 | image = str(top_list.xpath('//*[@id="7d"]/ul/li[%d]/big[1]/@class' % i)[0]).split(" ")[1]
158 | temp = get_weather_tem(top_list, i)
159 | if "℃" not in str(temp):
160 | temp += "℃"
161 | weather_data = {
162 | "date": str(date).split("(")[0],
163 | "weather": weather,
164 | "temp": temp,
165 | "image": image
166 | }
167 | weather_list.append(weather_data)
168 | except Exception as e:
169 | print("Error:{0}".format(e))
170 | return weather_list
171 |
172 |
173 | def get_weather_tem(top, index):
174 | """
175 | 获取温度(供get_weather_info函数调用)
176 | """
177 | tem_low = top.xpath('li[%d]/p[@class="tem"]/i/text()' % index)[0]
178 | if len(top.xpath('li[%d]/p[@class="tem"]/span' % index)) != 0:
179 | tem_high = top.xpath('li[%d]/p[@class="tem"]/span/text()' % index)[0]
180 | return str(tem_low).replace("℃", "") + '~' + tem_high
181 | else:
182 | return tem_low
183 |
184 |
185 | def get_weather_image(weather_data, base_image):
186 | """
187 | 根据图片class提取图片
188 | :param weather_data: 天气图片json
189 | :param base_image: QPixmap格式的图片
190 | :return: 对应的天气图标
191 | """
192 | for weather_image_local in weather_image_local_list:
193 | if weather_image_local['name'] == weather_data['image']:
194 | return base_image.copy(int(weather_image_local['x']), int(weather_image_local['y']), 80, 80)
195 |
--------------------------------------------------------------------------------
/city_form.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 234
10 | 248
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 7
20 | 32
21 | 218
22 | 201
23 |
24 |
25 |
26 |
27 | 思源黑体
28 |
29 |
30 |
31 | border-style: solid;
32 | border-radius: 10px;
33 | border: 1px groove gray;
34 | color: rgb(0, 0, 0);
35 | border-color: rgba(255, 255, 255, 1);
36 | background-color: rgba(255, 255, 255, 1);
37 |
38 |
39 | QFrame::StyledPanel
40 |
41 |
42 | 1
43 |
44 |
45 | true
46 |
47 |
48 |
49 |
50 | 0
51 | 0
52 | 216
53 | 199
54 |
55 |
56 |
57 |
58 |
59 | 20
60 | 95
61 | 61
62 | 21
63 |
64 |
65 |
66 |
67 | 思源黑体
68 | 11
69 |
70 |
71 |
72 | 选择市:
73 |
74 |
75 |
76 |
77 |
78 | 82
79 | 93
80 | 111
81 | 25
82 |
83 |
84 |
85 |
86 | 12
87 |
88 |
89 |
90 | border-style: solid;
91 | border-radius: 3px;
92 | border: 1px groove gray;
93 | color: rgb(0, 0, 0);
94 | border-color: rgb(0, 0, 0);
95 | background-color: rgb(255, 255, 255);
96 |
97 |
98 |
99 |
100 |
101 | 82
102 | 13
103 | 111
104 | 25
105 |
106 |
107 |
108 |
109 | 12
110 |
111 |
112 |
113 | border-style: solid;
114 | border-radius: 3px;
115 | border: 1px groove gray;
116 | color: rgb(0, 0, 0);
117 | border-color: rgb(0, 0, 0);
118 | background-color: rgb(255, 255, 255);
119 |
120 |
121 |
122 |
123 |
124 | 20
125 | 55
126 | 61
127 | 21
128 |
129 |
130 |
131 |
132 | 思源黑体
133 | 11
134 |
135 |
136 |
137 | 选择市:
138 |
139 |
140 |
141 |
142 |
143 | 70
144 | 160
145 | 61
146 | 21
147 |
148 |
149 |
150 |
151 | 思源黑体
152 | 10
153 |
154 |
155 |
156 | QPushButton {
157 | border-style: solid;
158 | border-radius: 10px;
159 | border: 0px groove gray;
160 | color: #FFFFFF;
161 | border-color: #000000;
162 | background-color: rgba(0, 0, 0, 0.3);
163 | }
164 | QPushButton:hover {
165 | background: rgba(255, 255, 255, 0.5);
166 | color: rgb(0, 0, 0);
167 | border: 1px groove gray;
168 | }
169 |
170 |
171 | 确定
172 |
173 |
174 |
175 |
176 |
177 | 20
178 | 15
179 | 61
180 | 21
181 |
182 |
183 |
184 |
185 | 思源黑体
186 | 11
187 |
188 |
189 |
190 | 选择省:
191 |
192 |
193 |
194 |
195 |
196 | 82
197 | 53
198 | 111
199 | 25
200 |
201 |
202 |
203 |
204 | 12
205 |
206 |
207 |
208 | border-style: solid;
209 | border-radius: 3px;
210 | border: 1px groove gray;
211 | color: rgb(0, 0, 0);
212 | border-color: rgb(0, 0, 0);
213 | background-color: rgb(255, 255, 255);
214 |
215 |
216 |
217 |
218 |
219 | 10
220 | 130
221 | 191
222 | 20
223 |
224 |
225 |
226 | 如果选择出现问题请尝试重启软件
227 |
228 |
229 | Qt::AlignCenter
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 | 20
238 | 5
239 | 81
240 | 35
241 |
242 |
243 |
244 |
245 | 思源黑体
246 | 11
247 |
248 |
249 |
250 | QPushButton {
251 | border-style: solid;
252 | border-radius: 10px;
253 | color: #FFFFFF;
254 | border-color: #000000;
255 | background-color: rgba(0, 0, 0, 0.3);
256 | }
257 |
258 |
259 | 选择城市
260 |
261 |
262 | push_button_60s_news
263 | scroll_area
264 |
265 |
266 |
267 |
268 | combo_box_province
269 | currentTextChanged(QString)
270 | Form
271 | slot_province_click()
272 |
273 |
274 | 144
275 | 64
276 |
277 |
278 | 231
279 | 66
280 |
281 |
282 |
283 |
284 | combo_box_city
285 | currentTextChanged(QString)
286 | Form
287 | slot_city_click()
288 |
289 |
290 | 163
291 | 107
292 |
293 |
294 | 227
295 | 110
296 |
297 |
298 |
299 |
300 | push_button_ok
301 | clicked()
302 | Form
303 | push_button_ok_click()
304 |
305 |
306 | 137
307 | 203
308 |
309 |
310 | 205
311 | 200
312 |
313 |
314 |
315 |
316 |
317 | push_button_ok_click()
318 | slot_province_click()
319 | slot_city_click()
320 |
321 |
322 |
--------------------------------------------------------------------------------
/new_todo_form.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'new_todo_form.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.15.4
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 | from PySide2 import QtCore, QtGui, QtWidgets
12 |
13 |
14 | class Ui_Form(object):
15 | def setupUi(self, Form):
16 | Form.setObjectName("Form")
17 | Form.resize(387, 421)
18 | self.scroll_area = QtWidgets.QScrollArea(Form)
19 | self.scroll_area.setGeometry(QtCore.QRect(7, 32, 371, 381))
20 | font = QtGui.QFont()
21 | font.setFamily("思源黑体")
22 | self.scroll_area.setFont(font)
23 | self.scroll_area.setStyleSheet(" border-style: solid;\n"
24 | " border-radius: 10px;\n"
25 | " border: 1px groove gray;\n"
26 | " color: rgb(0, 0, 0);\n"
27 | " border-color: rgba(255, 255, 255, 1);\n"
28 | " background-color: rgba(255, 255, 255, 1);")
29 | self.scroll_area.setFrameShape(QtWidgets.QFrame.StyledPanel)
30 | self.scroll_area.setLineWidth(1)
31 | self.scroll_area.setWidgetResizable(True)
32 | self.scroll_area.setObjectName("scroll_area")
33 | self.scrollAreaWidgetContents = QtWidgets.QWidget()
34 | self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 369, 379))
35 | self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
36 | self.text_edit_des = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
37 | self.text_edit_des.setGeometry(QtCore.QRect(13, 90, 341, 121))
38 | font = QtGui.QFont()
39 | font.setFamily("思源黑体")
40 | font.setPointSize(10)
41 | self.text_edit_des.setFont(font)
42 | self.text_edit_des.setStyleSheet(" border-style: solid;\n"
43 | " border-radius: 3px;\n"
44 | " border: 1px groove gray;\n"
45 | " color: rgb(0, 0, 0);\n"
46 | " border-color: rgb(0, 0, 0);\n"
47 | " background-color: rgb(255, 255, 255);")
48 | self.text_edit_des.setObjectName("text_edit_des")
49 | self.label_12 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
50 | self.label_12.setGeometry(QtCore.QRect(13, 222, 81, 18))
51 | font = QtGui.QFont()
52 | font.setFamily("思源黑体")
53 | font.setPointSize(11)
54 | self.label_12.setFont(font)
55 | self.label_12.setStyleSheet(" color: #000000;\n"
56 | " background-color: rgba(0, 0, 0, 0);")
57 | self.label_12.setObjectName("label_12")
58 | self.push_button_cancel = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
59 | self.push_button_cancel.setGeometry(QtCore.QRect(73, 344, 51, 25))
60 | font = QtGui.QFont()
61 | font.setFamily("思源黑体")
62 | font.setPointSize(10)
63 | font.setBold(False)
64 | font.setWeight(50)
65 | font.setKerning(True)
66 | self.push_button_cancel.setFont(font)
67 | self.push_button_cancel.setStyleSheet("QPushButton {\n"
68 | " border-style: solid;\n"
69 | " border-radius: 10px;\n"
70 | " border: 0px groove gray;\n"
71 | " color: #FFFFFF;\n"
72 | " border-color: #000000;\n"
73 | " background-color: rgba(0, 0, 0, 0.3);\n"
74 | "}\n"
75 | "QPushButton:hover {\n"
76 | " background: rgba(255, 255, 255, 0.5);\n"
77 | " color: rgb(0, 0, 0);\n"
78 | " border: 1px groove gray;\n"
79 | "}")
80 | self.push_button_cancel.setObjectName("push_button_cancel")
81 | self.label_9 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
82 | self.label_9.setGeometry(QtCore.QRect(13, 68, 45, 18))
83 | font = QtGui.QFont()
84 | font.setFamily("思源黑体")
85 | font.setPointSize(11)
86 | self.label_9.setFont(font)
87 | self.label_9.setStyleSheet(" color: #000000;\n"
88 | " background-color: rgba(0, 0, 0, 0);")
89 | self.label_9.setObjectName("label_9")
90 | self.label_8 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
91 | self.label_8.setGeometry(QtCore.QRect(13, 13, 45, 18))
92 | font = QtGui.QFont()
93 | font.setFamily("思源黑体")
94 | font.setPointSize(11)
95 | self.label_8.setFont(font)
96 | self.label_8.setStyleSheet(" color: #000000;\n"
97 | " background-color: rgba(0, 0, 0, 0);")
98 | self.label_8.setObjectName("label_8")
99 | self.push_button_success = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
100 | self.push_button_success.setGeometry(QtCore.QRect(233, 344, 51, 25))
101 | font = QtGui.QFont()
102 | font.setFamily("思源黑体")
103 | font.setPointSize(10)
104 | font.setBold(False)
105 | font.setWeight(50)
106 | font.setKerning(True)
107 | self.push_button_success.setFont(font)
108 | self.push_button_success.setStyleSheet("QPushButton {\n"
109 | " border-style: solid;\n"
110 | " border-radius: 10px;\n"
111 | " border: 0px groove gray;\n"
112 | " color: #FFFFFF;\n"
113 | " border-color: #000000;\n"
114 | " background-color: rgba(0, 0, 0, 0.3);\n"
115 | "}\n"
116 | "QPushButton:hover {\n"
117 | " background: rgba(255, 255, 255, 0.5);\n"
118 | " color: rgb(0, 0, 0);\n"
119 | " border: 1px groove gray;\n"
120 | "}")
121 | self.push_button_success.setObjectName("push_button_success")
122 | self.combo_box_degree = QtWidgets.QComboBox(self.scrollAreaWidgetContents)
123 | self.combo_box_degree.setGeometry(QtCore.QRect(13, 244, 341, 22))
124 | font = QtGui.QFont()
125 | font.setFamily("思源黑体 Normal")
126 | self.combo_box_degree.setFont(font)
127 | self.combo_box_degree.setStyleSheet(" border-style: solid;\n"
128 | " border-radius: 3px;\n"
129 | " border: 1px groove gray;\n"
130 | " color: rgb(0, 0, 0);\n"
131 | " border-color: rgb(0, 0, 0);\n"
132 | " background-color: rgb(255, 255, 255);")
133 | self.combo_box_degree.setObjectName("combo_box_degree")
134 | self.combo_box_degree.addItem("")
135 | self.combo_box_degree.addItem("")
136 | self.combo_box_degree.addItem("")
137 | self.label_11 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
138 | self.label_11.setGeometry(QtCore.QRect(13, 274, 81, 18))
139 | font = QtGui.QFont()
140 | font.setFamily("思源黑体")
141 | font.setPointSize(11)
142 | self.label_11.setFont(font)
143 | self.label_11.setStyleSheet(" color: #000000;\n"
144 | " background-color: rgba(0, 0, 0, 0);")
145 | self.label_11.setObjectName("label_11")
146 | self.line_edit_title = QtWidgets.QLineEdit(self.scrollAreaWidgetContents)
147 | self.line_edit_title.setGeometry(QtCore.QRect(13, 35, 341, 25))
148 | font = QtGui.QFont()
149 | font.setFamily("思源黑体")
150 | font.setPointSize(11)
151 | self.line_edit_title.setFont(font)
152 | self.line_edit_title.setStyleSheet(" border-style: solid;\n"
153 | " border-radius: 3px;\n"
154 | " border: 1px groove gray;\n"
155 | " color: rgb(0, 0, 0);\n"
156 | " border-color: rgb(0, 0, 0);\n"
157 | " background-color: rgb(255, 255, 255);")
158 | self.line_edit_title.setObjectName("line_edit_title")
159 | self.check_push_button = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
160 | self.check_push_button.setGeometry(QtCore.QRect(15, 298, 18, 18))
161 | font = QtGui.QFont()
162 | font.setFamily("思源黑体")
163 | font.setPointSize(9)
164 | self.check_push_button.setFont(font)
165 | self.check_push_button.setStyleSheet("border-style: solid;\n"
166 | "border-radius: 9px;\n"
167 | "border: 1px groove #000;\n"
168 | "color: rgb(255, 255, 255);\n"
169 | "border-color: rgba(0, 0, 0, 0.5);\n"
170 | "background-color: rgb(255, 255, 255);")
171 | self.check_push_button.setText("")
172 | self.check_push_button.setIconSize(QtCore.QSize(14, 14))
173 | self.check_push_button.setObjectName("check_push_button")
174 | self.date_time_edit = QtWidgets.QDateTimeEdit(self.scrollAreaWidgetContents)
175 | self.date_time_edit.setGeometry(QtCore.QRect(43, 296, 311, 22))
176 | font = QtGui.QFont()
177 | font.setFamily("思源黑体")
178 | self.date_time_edit.setFont(font)
179 | self.date_time_edit.setStyleSheet(" border-style: solid;\n"
180 | " border-radius: 3px;\n"
181 | " border: 1px groove gray;\n"
182 | " color: rgb(0, 0, 0);\n"
183 | " border-color: rgb(0, 0, 0);\n"
184 | " background-color: rgb(255, 255, 255);")
185 | self.date_time_edit.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
186 | self.date_time_edit.setCurrentSection(QtWidgets.QDateTimeEdit.YearSection)
187 | self.date_time_edit.setCalendarPopup(False)
188 | self.date_time_edit.setObjectName("date_time_edit")
189 | self.scroll_area.setWidget(self.scrollAreaWidgetContents)
190 | self.push_button_60s_news = QtWidgets.QPushButton(Form)
191 | self.push_button_60s_news.setGeometry(QtCore.QRect(20, 5, 101, 35))
192 | font = QtGui.QFont()
193 | font.setFamily("思源黑体")
194 | font.setPointSize(11)
195 | self.push_button_60s_news.setFont(font)
196 | self.push_button_60s_news.setStyleSheet("QPushButton {\n"
197 | " border-style: solid;\n"
198 | " border-radius: 10px;\n"
199 | " color: #FFFFFF;\n"
200 | " border-color: #000000;\n"
201 | " background-color: rgba(0, 0, 0, 0.3);\n"
202 | "}")
203 | self.push_button_60s_news.setObjectName("push_button_60s_news")
204 | self.push_button_60s_news.raise_()
205 | self.scroll_area.raise_()
206 |
207 | self.retranslateUi(Form)
208 | QtCore.QMetaObject.connectSlotsByName(Form)
209 |
210 | def retranslateUi(self, Form):
211 | _translate = QtCore.QCoreApplication.translate
212 | Form.setWindowTitle(_translate("Form", "Form"))
213 | self.label_12.setText(_translate("Form", "程度:"))
214 | self.push_button_cancel.setText(_translate("Form", "取消"))
215 | self.label_9.setText(_translate("Form", "内容:"))
216 | self.label_8.setText(_translate("Form", "标题:"))
217 | self.push_button_success.setText(_translate("Form", "确定"))
218 | self.combo_box_degree.setItemText(0, _translate("Form", "紧急"))
219 | self.combo_box_degree.setItemText(1, _translate("Form", "一般"))
220 | self.combo_box_degree.setItemText(2, _translate("Form", "莫慌"))
221 | self.label_11.setText(_translate("Form", "闹钟:"))
222 | self.date_time_edit.setDisplayFormat(_translate("Form", "yyyy-MM-dd HH:mm"))
223 | self.push_button_60s_news.setText(_translate("Form", "新增待办事项"))
224 |
--------------------------------------------------------------------------------
/my_component/MyListWidget.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from PySide2 import QtCore, QtGui, QtWidgets
3 | from PySide2.QtWidgets import *
4 | from PySide2.QtCore import Qt
5 |
6 |
7 | def get_font(family, size):
8 | font = QtGui.QFont()
9 | font.setFamily(family)
10 | font.setPointSize(size)
11 | return font
12 |
13 |
14 | class MyQWidgetItem(QWidget):
15 |
16 | label_title = None
17 | blank_left_label = None
18 | check_push_button = None
19 | delete_button = None
20 | degree_line = None
21 | blank_label = None
22 | warn_label = None
23 | separation_line = None
24 |
25 | def __init__(self, parent=None, todo_id="", title="", success=False, degree="First", warn=False, time_str=""):
26 | super(MyQWidgetItem, self).__init__(parent)
27 | self.todo_id = todo_id
28 | # 标题
29 | self.label_title = QtWidgets.QLabel(parent)
30 | self.label_title.setFont(get_font("思源黑体", 11))
31 | self.label_title.setMinimumWidth(260)
32 | self.label_title.setMaximumHeight(23)
33 | self.label_title.setStyleSheet("border: 0px solid #FF8D16;border-radius: 0px;background-color: rgba(0, 0, 0, 0);")
34 | self.label_title.setText(title)
35 | # 勾选框左边的的占位
36 | self.blank_left_label = QtWidgets.QLabel(parent)
37 | self.blank_left_label.setFixedSize(5, 10)
38 | self.blank_left_label.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
39 | self.blank_left_label.setText("")
40 | # 勾选框
41 | self.check_push_button = QtWidgets.QPushButton(parent)
42 | self.check_push_button.setFixedSize(18, 18)
43 | self.check_push_button.setFont(get_font("思源黑体", 9))
44 | self.check_push_button.setIconSize(QtCore.QSize(14, 14))
45 | if success:
46 | self.check_push_button.setText("✓")
47 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 0px groove #000;\n"
48 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgba(0, 0, 0, 0.5);")
49 | else:
50 | self.check_push_button.setText("")
51 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 1px groove #000;\n"
52 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgb(255, 255, 255);")
53 | # 删除按钮
54 | self.delete_button = QtWidgets.QPushButton(parent)
55 | self.delete_button.setFixedSize(25, 25)
56 | font = get_font("幼圆", 13)
57 | font.setBold(True)
58 | font.setWeight(75)
59 | self.delete_button.setFont(font)
60 | self.delete_button.setStyleSheet("color: rgb(166, 166, 166);")
61 | self.delete_button.setText("×")
62 | # 程度条
63 | self.degree_line = QtWidgets.QFrame(parent)
64 | if warn:
65 | self.degree_line.setFixedSize(6, 50)
66 | else:
67 | self.degree_line.setFixedSize(6, 40)
68 | self.degree_line.setFrameShape(QtWidgets.QFrame.VLine)
69 | self.degree_line.setFrameShadow(QtWidgets.QFrame.Sunken)
70 | if degree == "First":
71 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(212, 63, 54, 0.8);\n"
72 | "border-color: rgba(212, 63, 54, 0.8);background-color: rgba(212, 63, 54, 0.8);")
73 | elif degree == "Second":
74 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(255, 139, 42, 0.8);\n"
75 | "border-color: rgba(255, 139, 42, 0.8);background-color: rgba(255, 139, 42, 0.8);")
76 | elif degree == "Third":
77 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(164, 207, 48, 0.8);\n"
78 | "border-color: rgba(164, 207, 48, 0.8);background-color: rgba(164, 207, 48, 0.8);")
79 | # 提醒时间
80 | if warn:
81 | # 勾选框下的占位
82 | self.blank_label = QtWidgets.QLabel(parent)
83 | self.blank_label.setFixedSize(1, 10)
84 | self.blank_label.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
85 | self.blank_label.setText("")
86 | # 提醒时间
87 | self.warn_label = QtWidgets.QLabel(parent)
88 | self.warn_label.setFixedSize(160, 18)
89 | self.warn_label.setFont(get_font("思源黑体", 9))
90 | self.warn_label.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
91 | self.warn_label.setText("🔔 " + time_str[:16])
92 | # 分隔符
93 | self.separation_line = QtWidgets.QFrame(parent)
94 | self.separation_line.setFixedSize(374, 1)
95 | self.separation_line.setMaximumHeight(1)
96 | self.separation_line.setStyleSheet("color: rgba(200, 200, 200, 0.3);border-color: rgba(200, 200, 200, 0.3);"
97 | "background-color: rgba(200, 200, 200, 0.3);")
98 | self.separation_line.setFrameShape(QtWidgets.QFrame.HLine)
99 | self.separation_line.setFrameShadow(QtWidgets.QFrame.Sunken)
100 | # 布局
101 | self.main_layout = QtWidgets.QHBoxLayout()
102 | self.main_layout.setContentsMargins(0, 4, 0, 0)
103 | self.main_layout.addWidget(self.degree_line)
104 | self.main_layout.addWidget(self.blank_left_label)
105 | self.check_and_blank_layout = QtWidgets.QVBoxLayout()
106 | self.check_and_blank_layout.setContentsMargins(0, 0, 0, 0)
107 | if warn:
108 | self.check_and_blank_layout.addWidget(self.check_push_button)
109 | self.check_and_blank_layout.addWidget(self.blank_label)
110 | else:
111 | self.check_and_blank_layout.addWidget(self.check_push_button)
112 | self.main_layout.addLayout(self.check_and_blank_layout)
113 | self.title_and_warn_layout = QtWidgets.QVBoxLayout()
114 | self.title_and_warn_layout.setContentsMargins(0, 0, 0, 0)
115 | if warn:
116 | self.title_and_warn_layout.addWidget(self.label_title)
117 | self.title_and_warn_layout.addWidget(self.warn_label)
118 | else:
119 | self.title_and_warn_layout.addWidget(self.label_title)
120 | self.main_layout.addLayout(self.title_and_warn_layout)
121 | self.main_layout.addWidget(self.delete_button)
122 | self.main_layout.setAlignment(self.delete_button, Qt.AlignCenter)
123 | self.layout = QtWidgets.QVBoxLayout()
124 | self.layout.setContentsMargins(0, 0, 0, 0)
125 | self.layout.addLayout(self.main_layout)
126 | self.layout.addWidget(self.separation_line)
127 | self.setLayout(self.layout)
128 |
129 | def set_custom_title(self, text):
130 | self.label_title.setText(text)
131 |
132 | def set_custom_success(self, success):
133 | if success:
134 | self.check_push_button.setText("✓")
135 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 0px groove #000;\n"
136 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgba(0, 0, 0, 0.5);")
137 | else:
138 | self.check_push_button.setText("")
139 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 1px groove #000;\n"
140 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgb(255, 255, 255);")
141 |
142 | def set_custom_degree(self, degree):
143 | if degree == "First":
144 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(212, 63, 54, 0.8);\n"
145 | "border-color: rgba(212, 63, 54, 0.8);background-color: rgba(212, 63, 54, 0.8);")
146 | elif degree == "Second":
147 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(255, 139, 42, 0.8);\n"
148 | "border-color: rgba(255, 139, 42, 0.8);background-color: rgba(255, 139, 42, 0.8);")
149 | elif degree == "Third":
150 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(164, 207, 48, 0.8);\n"
151 | "border-color: rgba(164, 207, 48, 0.8);background-color: rgba(164, 207, 48, 0.8);")
152 |
153 | def set_all(self, parent=None, todo_id="", title="", success=False, degree="First", warn=False, time_str=""):
154 | self.todo_id = todo_id
155 | # 标题
156 | self.label_title.setText(title)
157 | # 勾选框
158 | if success:
159 | self.check_push_button.setText("✓")
160 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 0px groove #000;\n"
161 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgba(0, 0, 0, 0.5);")
162 | else:
163 | self.check_push_button.setText("")
164 | self.check_push_button.setStyleSheet("border-style: solid;border-radius: 9px;border: 1px groove #000;\n"
165 | "color: rgb(255, 255, 255);border-color: rgba(0, 0, 0, 0.5);background-color: rgb(255, 255, 255);")
166 | # 程度条
167 | if warn:
168 | self.degree_line.setFixedSize(6, 50)
169 | else:
170 | self.degree_line.setFixedSize(6, 40)
171 | if degree == "First":
172 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(212, 63, 54, 0.8);\n"
173 | "border-color: rgba(212, 63, 54, 0.8);background-color: rgba(212, 63, 54, 0.8);")
174 | elif degree == "Second":
175 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(255, 139, 42, 0.8);\n"
176 | "border-color: rgba(255, 139, 42, 0.8);background-color: rgba(255, 139, 42, 0.8);")
177 | elif degree == "Third":
178 | self.degree_line.setStyleSheet("border-style: solid;border-radius: 3px;color: rgba(164, 207, 48, 0.8);\n"
179 | "border-color: rgba(164, 207, 48, 0.8);background-color: rgba(164, 207, 48, 0.8);")
180 | # 提醒时间
181 | if warn:
182 | if self.blank_label is None:
183 | # 勾选框下的占位
184 | self.blank_label = QtWidgets.QLabel(parent)
185 | self.blank_label.setFixedSize(1, 10)
186 | self.blank_label.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
187 | self.blank_label.setText("")
188 | # 提醒时间
189 | self.warn_label = QtWidgets.QLabel(parent)
190 | self.warn_label.setFixedSize(160, 18)
191 | self.warn_label.setFont(get_font("思源黑体", 9))
192 | self.warn_label.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
193 | self.warn_label.setText("🔔 " + time_str[:16])
194 | self.check_and_blank_layout.addWidget(self.blank_label)
195 | self.title_and_warn_layout.addWidget(self.warn_label)
196 | else:
197 | self.warn_label.setText("🔔 " + time_str[:16])
198 | else:
199 | if self.blank_label is not None:
200 | self.check_and_blank_layout.removeWidget(self.blank_label)
201 | self.title_and_warn_layout.removeWidget(self.warn_label)
202 | self.blank_label.clear()
203 | self.blank_label = None
204 | self.warn_label.clear()
205 | self.warn_label = None
--------------------------------------------------------------------------------
/new_todo_form.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 387
10 | 421
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 7
20 | 32
21 | 371
22 | 381
23 |
24 |
25 |
26 |
27 | 思源黑体
28 |
29 |
30 |
31 | border-style: solid;
32 | border-radius: 10px;
33 | border: 1px groove gray;
34 | color: rgb(0, 0, 0);
35 | border-color: rgba(255, 255, 255, 1);
36 | background-color: rgba(255, 255, 255, 1);
37 |
38 |
39 | QFrame::StyledPanel
40 |
41 |
42 | 1
43 |
44 |
45 | true
46 |
47 |
48 |
49 |
50 | 0
51 | 0
52 | 369
53 | 379
54 |
55 |
56 |
57 |
58 |
59 | 13
60 | 90
61 | 341
62 | 121
63 |
64 |
65 |
66 |
67 | 思源黑体
68 | 10
69 |
70 |
71 |
72 | border-style: solid;
73 | border-radius: 3px;
74 | border: 1px groove gray;
75 | color: rgb(0, 0, 0);
76 | border-color: rgb(0, 0, 0);
77 | background-color: rgb(255, 255, 255);
78 |
79 |
80 |
81 |
82 |
83 | 13
84 | 222
85 | 81
86 | 18
87 |
88 |
89 |
90 |
91 | 思源黑体
92 | 11
93 |
94 |
95 |
96 | color: #000000;
97 | background-color: rgba(0, 0, 0, 0);
98 |
99 |
100 | 程度:
101 |
102 |
103 |
104 |
105 |
106 | 73
107 | 344
108 | 51
109 | 25
110 |
111 |
112 |
113 |
114 | 思源黑体
115 | 10
116 | 50
117 | false
118 | true
119 |
120 |
121 |
122 | QPushButton {
123 | border-style: solid;
124 | border-radius: 10px;
125 | border: 0px groove gray;
126 | color: #FFFFFF;
127 | border-color: #000000;
128 | background-color: rgba(0, 0, 0, 0.3);
129 | }
130 | QPushButton:hover {
131 | background: rgba(255, 255, 255, 0.5);
132 | color: rgb(0, 0, 0);
133 | border: 1px groove gray;
134 | }
135 |
136 |
137 | 取消
138 |
139 |
140 |
141 |
142 |
143 | 13
144 | 68
145 | 45
146 | 18
147 |
148 |
149 |
150 |
151 | 思源黑体
152 | 11
153 |
154 |
155 |
156 | color: #000000;
157 | background-color: rgba(0, 0, 0, 0);
158 |
159 |
160 | 内容:
161 |
162 |
163 |
164 |
165 |
166 | 13
167 | 13
168 | 45
169 | 18
170 |
171 |
172 |
173 |
174 | 思源黑体
175 | 11
176 |
177 |
178 |
179 | color: #000000;
180 | background-color: rgba(0, 0, 0, 0);
181 |
182 |
183 | 标题:
184 |
185 |
186 |
187 |
188 |
189 | 233
190 | 344
191 | 51
192 | 25
193 |
194 |
195 |
196 |
197 | 思源黑体
198 | 10
199 | 50
200 | false
201 | true
202 |
203 |
204 |
205 | QPushButton {
206 | border-style: solid;
207 | border-radius: 10px;
208 | border: 0px groove gray;
209 | color: #FFFFFF;
210 | border-color: #000000;
211 | background-color: rgba(0, 0, 0, 0.3);
212 | }
213 | QPushButton:hover {
214 | background: rgba(255, 255, 255, 0.5);
215 | color: rgb(0, 0, 0);
216 | border: 1px groove gray;
217 | }
218 |
219 |
220 | 确定
221 |
222 |
223 |
224 |
225 |
226 | 13
227 | 244
228 | 341
229 | 22
230 |
231 |
232 |
233 |
234 | 思源黑体 Normal
235 |
236 |
237 |
238 | border-style: solid;
239 | border-radius: 3px;
240 | border: 1px groove gray;
241 | color: rgb(0, 0, 0);
242 | border-color: rgb(0, 0, 0);
243 | background-color: rgb(255, 255, 255);
244 |
245 | -
246 |
247 | 紧急
248 |
249 |
250 | -
251 |
252 | 一般
253 |
254 |
255 | -
256 |
257 | 莫慌
258 |
259 |
260 |
261 |
262 |
263 |
264 | 13
265 | 274
266 | 81
267 | 18
268 |
269 |
270 |
271 |
272 | 思源黑体
273 | 11
274 |
275 |
276 |
277 | color: #000000;
278 | background-color: rgba(0, 0, 0, 0);
279 |
280 |
281 | 闹钟:
282 |
283 |
284 |
285 |
286 |
287 | 13
288 | 35
289 | 341
290 | 25
291 |
292 |
293 |
294 |
295 | 思源黑体
296 | 11
297 |
298 |
299 |
300 | border-style: solid;
301 | border-radius: 3px;
302 | border: 1px groove gray;
303 | color: rgb(0, 0, 0);
304 | border-color: rgb(0, 0, 0);
305 | background-color: rgb(255, 255, 255);
306 |
307 |
308 |
309 |
310 |
311 | 15
312 | 298
313 | 18
314 | 18
315 |
316 |
317 |
318 |
319 | 思源黑体
320 | 9
321 |
322 |
323 |
324 | border-style: solid;
325 | border-radius: 9px;
326 | border: 1px groove #000;
327 | color: rgb(255, 255, 255);
328 | border-color: rgba(0, 0, 0, 0.5);
329 | background-color: rgb(255, 255, 255);
330 |
331 |
332 |
333 |
334 |
335 |
336 | 14
337 | 14
338 |
339 |
340 |
341 |
342 |
343 |
344 | 43
345 | 296
346 | 311
347 | 22
348 |
349 |
350 |
351 |
352 | 思源黑体
353 |
354 |
355 |
356 | border-style: solid;
357 | border-radius: 3px;
358 | border: 1px groove gray;
359 | color: rgb(0, 0, 0);
360 | border-color: rgb(0, 0, 0);
361 | background-color: rgb(255, 255, 255);
362 |
363 |
364 | QAbstractSpinBox::NoButtons
365 |
366 |
367 | QDateTimeEdit::YearSection
368 |
369 |
370 | yyyy-MM-dd HH:mm
371 |
372 |
373 | false
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 | 20
382 | 5
383 | 101
384 | 35
385 |
386 |
387 |
388 |
389 | 思源黑体
390 | 11
391 |
392 |
393 |
394 | QPushButton {
395 | border-style: solid;
396 | border-radius: 10px;
397 | color: #FFFFFF;
398 | border-color: #000000;
399 | background-color: rgba(0, 0, 0, 0.3);
400 | }
401 |
402 |
403 | 新增待办事项
404 |
405 |
406 | push_button_60s_news
407 | scroll_area
408 |
409 |
410 |
411 |
412 |
--------------------------------------------------------------------------------
/get_info/get_micro_blog_info.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: UTF-8 -*-
3 | """
4 | name: 获取微博信息
5 | by: baby7
6 | blog: https://www.baby7blog.com
7 | annotation: 获取微博信息,例如热搜榜等
8 | """
9 | import re
10 | import time
11 | import random
12 | import requests
13 | from lxml import etree
14 | from urllib.parse import quote
15 |
16 | import browser_cookie3
17 |
18 | __all__ = ['judge_add']
19 |
20 |
21 | def get_base_info():
22 | try:
23 | # 输出时间戳
24 | now_timestamp = int(time.time() * 1000)
25 | sina_global = str(int(random.random() * 10000000000000)) + "." + str(int(random.random() * 10000)) \
26 | + "." + str(now_timestamp - 14 - 1072340 - 6)
27 | apache = str(int(random.random() * 10000000000000)) + "." + str(int(random.random() * 10000)) \
28 | + "." + str(now_timestamp - 14)
29 | ulv = str(now_timestamp) + ":2:2:2:" \
30 | + str(int(random.random() * 10000000000000)) + "." + str(int(random.random() * 10000)) \
31 | + "." + str(now_timestamp - 14) \
32 | + ":" + str(now_timestamp - 14 - 1072340)
33 | cookie_result = 'SUB=_2AkMUqfltf8NxqwJRmPEVz2Pib4V_zwrEieKi9Qi2JRMxHRl-yT9kqk0ttRB6PynXgT5CUZzGwlh-mIyUQvhe-_yXXtj3; ' + \
34 | 'SUBP=0033WrSXqPxfM72-Ws9jqgMF55529P9D9WFyRDSrne6a4e.bkQHJzd-.; ' + \
35 | 'SINAGLOBAL=' + sina_global + '; _s_tentry=-; ' + \
36 | 'Apache=' + apache + '; ' + \
37 | 'ULV=' + ulv
38 | # 请求头
39 | header = {
40 | 'cookie': cookie_result,
41 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.50',
42 | }
43 | res = requests.get(url="https://s.weibo.com/top/summary?cate=realtimehot", headers=header, timeout=3)
44 | return res
45 | except Exception as e:
46 | print("Error:{0}".format(e))
47 | return {"text": "403 Forbidden"}
48 |
49 |
50 | def get_hot_search_list(search_all, screen_word_list, screen_type_list, logger):
51 | """
52 | 获取热搜榜(screen_word_list和screen_type_list为并集,不是交集)
53 | :param search_all: 查询所有的,优先级高于后面的筛选
54 | :param screen_word_list: 筛选关键词列表,为空表示不查询,进行筛序的话例如:['流浪地球', '刘德华']
55 | :param screen_type_list: 筛选类型列表,为空表示不查询,进行筛序的话例如:['new'(新),'hot'(热),'boil'(沸),'boom'(爆)]
56 | :return: 热搜榜
57 | """
58 | try:
59 | res = get_base_info()
60 | if "403 Forbidden" in str(res.text):
61 | return "Login"
62 | # print(res.text)
63 | html = etree.HTML(res.text) # 转化成html文件
64 | hot_search_list = []
65 | if "pl_top_realtimehot" not in str(res.text):
66 | search_list = html.xpath("//section[@class='list']/ul/li") # 提取数据
67 | for search_item in search_list:
68 | search_item_type = search_item.xpath(".//strong/@class")
69 | # 排除非热搜榜的信息
70 | if search_item_type is None or len(search_item_type) == 0 or search_item_type[0] != "hot":
71 | continue
72 | # 热搜排名
73 | search_item_index = str(search_item.xpath(".//strong/text()")[0])
74 | # 热搜标题
75 | search_item_title = str(search_item.xpath(".//span/text()")[0])
76 | # 热搜地址(这里无法使用带参数的地址,如果使用win10通知会不展示)
77 | # search_item_url = "https://s.weibo.com" + \
78 | # str(search_item.xpath(".//a/@href")[0]).split("%23&t=")[0]
79 | search_item_url = "https://s.weibo.com/weibo?q=" + quote("#" + search_item_title + "#")
80 | # 热搜火爆度
81 | search_item_count_data = search_item.xpath(".//span/em/text()")
82 | search_item_count = str(search_item_count_data[0]).replace(" ", "").replace("电影", "").replace("综艺", "")\
83 | .replace("剧集", "").replace("音乐", "") if \
84 | search_item_count_data is not None and len(search_item_count_data) > 0 else None
85 | # 热搜图标,"icon icon_new"表示新,"icon icon_hot"表示热,"icon icon_boil"表示沸,"icon icon_boom"表示爆
86 | search_item_icon_data = search_item.xpath(".//i/@class")
87 | search_item_icon = str(search_item_icon_data[0]) if \
88 | search_item_icon_data is not None and len(search_item_icon_data) > 0 else None
89 | # 组合数据
90 | search_item_data = {
91 | "index": search_item_index,
92 | "title": search_item_title,
93 | "url": search_item_url,
94 | "count": search_item_count,
95 | "icon": search_item_icon,
96 | }
97 | if judge_add(search_all, screen_word_list, screen_type_list, search_item_data):
98 | hot_search_list.append(search_item_data)
99 | else:
100 | search_list = html.xpath('//div[@id="pl_top_realtimehot"]/table/tbody/tr') # 提取数据
101 | for search_item in search_list:
102 | search_item_type = search_item.xpath('.//td[@class="td-01 ranktop"]/text()')
103 | # 排除非热搜榜的信息
104 | if search_item_type is None or len(search_item_type) == 0 or search_item_type[0] == '•':
105 | continue
106 | # 热搜排名
107 | search_item_index = str(search_item_type[0])
108 | # 热搜标题
109 | search_item_title = str(search_item.xpath('.//td[@class="td-02"]/a/text()')[0])
110 | # 热搜地址(这里无法使用带参数的地址,如果使用win10通知会不展示)
111 | # search_item_url = "https://s.weibo.com" + \
112 | # str(search_item.xpath('.//td[@class="td-02"]/a/@href')[0]).split("%23&t=")[0]
113 | search_item_url = "https://s.weibo.com/weibo?q=" + quote("#" + search_item_title + "#")
114 | # 热搜火爆度
115 | search_item_count_data = search_item.xpath('.//td[@class="td-02"]/span/text()')
116 | search_item_count = str(search_item_count_data[0]).replace(" ", "").replace("电影", "").replace("综艺", "")\
117 | .replace("剧集", "").replace("音乐", "") if \
118 | search_item_count_data is not None and len(search_item_count_data) > 0 else None
119 | # 热搜图标,"icon icon_new"表示新,"icon icon_hot"表示热,"icon icon_boil"表示沸,"icon icon_boom"表示爆
120 | search_item_icon_data = search_item.xpath('.//td[@class="td-03"]/i/@style')
121 | search_item_icon = str(search_item_icon_data[0]) if \
122 | search_item_icon_data is not None and len(search_item_icon_data) > 0 else None
123 | if search_item_icon is not None:
124 | if "#ff3852" in search_item_icon:
125 | search_item_icon = "icon icon_new"
126 | elif "#ff9406" in search_item_icon:
127 | search_item_icon = "icon icon_hot"
128 | elif "#f86400;" in search_item_icon:
129 | search_item_icon = "icon icon_boil"
130 | else:
131 | search_item_icon = "icon icon_boom"
132 | # 组合数据
133 | search_item_data = {
134 | "index": search_item_index,
135 | "title": search_item_title,
136 | "url": search_item_url,
137 | "count": search_item_count,
138 | "icon": search_item_icon,
139 | }
140 | if judge_add(search_all, screen_word_list, screen_type_list, search_item_data):
141 | hot_search_list.append(search_item_data)
142 | return hot_search_list
143 | except Exception as e:
144 | print("Error:{0}".format(e))
145 | logger.info("获取微博热搜错误:{0}".format(e))
146 | return []
147 |
148 |
149 | def judge_add(search_all,
150 | screen_word_list,
151 | screen_type_list,
152 | search_item_data):
153 | """
154 | 根据筛选条件是否需要添加
155 | :param search_all: 查询所有的,优先级高于后面的筛选
156 | :param screen_word_list: 筛选关键词列表,为空表示不查询,进行筛序的话例如:['流浪地球', '刘德华']
157 | :param screen_type_list: 筛选类型列表,为空表示不查询,进行筛序的话例如:['new'(新),'hot'(热),'boil'(沸),'boom'(爆)]
158 | :param search_item_data: 单条热搜对象
159 | :return: True需要,False不需要
160 | """
161 | if search_all:
162 | return True
163 | else:
164 | # 进行关键词判断
165 | add_tag = False
166 | if screen_word_list is not None and len(screen_word_list) > 0:
167 | for screen_word in screen_word_list:
168 | if screen_word in search_item_data['title']:
169 | add_tag = True
170 | break
171 | # 进行类型判断
172 | if screen_type_list is not None and len(screen_type_list) > 0:
173 | if search_item_data['icon'] is not None:
174 | for screen_type in screen_type_list:
175 | if screen_type in search_item_data['icon']:
176 | add_tag = True
177 | break
178 | if add_tag:
179 | return True
180 | return False
181 |
182 |
183 | # 处理成可以展示的html
184 | def change_css(html_content):
185 | # 热度标签样式
186 | html_content = html_content.replace("background-color:#bd0000;",
187 | 'background-color:#bd0000;display: inline-block;width: 16px;height: 16px;line-height: 16px;color: #fff;border-radius: 2px;text-align: center;font: 12px/1.3 Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;')
188 | html_content = html_content.replace("background-color:#ff3852;",
189 | 'background-color:#ff3852;display: inline-block;width: 16px;height: 16px;line-height: 16px;color: #fff;border-radius: 2px;text-align: center;font: 12px/1.3 Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;')
190 | html_content = html_content.replace("background-color:#ffab5a;",
191 | 'background-color:#ffab5a;display: inline-block;width: 16px;height: 16px;line-height: 16px;color: #fff;border-radius: 2px;text-align: center;font: 12px/1.3 Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;')
192 | html_content = html_content.replace("background-color:#ff9406;",
193 | 'background-color:#ff9406;display: inline-block;width: 16px;height: 16px;line-height: 16px;color: #fff;border-radius: 2px;text-align: center;font: 12px/1.3 Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;')
194 | html_content = html_content.replace("background-color:#f86400;",
195 | 'background-color:#f86400;display: inline-block;width: 16px;height: 16px;line-height: 16px;color: #fff;border-radius: 2px;text-align: center;font: 12px/1.3 Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;')
196 | html_content = html_content.replace('>新<', '> 新 <')
197 | html_content = html_content.replace('>热<', '> 热 <')
198 | html_content = html_content.replace('>暖<', '> 暖 <')
199 | html_content = html_content.replace('>沸<', '> 沸 <')
200 | html_content = html_content.replace('>爆<', '> 爆 <')
201 | # 去掉顶部热搜
202 | matches = re.findall('\n.*| .*\n.*\n.*\n.*\n.*\n.* |
', html_content)
203 | for match in matches:
204 | html_content = html_content.replace(match, "")
205 | # 去掉广告
206 | matches = re.findall('\n.*', html_content)
207 | for match in matches:
208 | html_content = html_content.replace(match, "")
209 | # 去掉图片
210 | matches = re.findall(' ', html_content)
211 | for match in matches:
212 | html_content = html_content.replace(match, "")
213 | # 热搜文字样式
214 | for index in range(51):
215 | if index <= 3:
216 | html_content = html_content.replace('class="td-01 ranktop ranktop' + str(index) + '"',
217 | 'class="td-01 ranktop ranktop' + str(index) + '" style="border-bottom:1px solid #f9f9f9;line-height:25px;color: #f26d5f;"')
218 | else:
219 | html_content = html_content.replace('class="td-01 ranktop ranktop' + str(index) + '"',
220 | 'class="td-01 ranktop ranktop' + str(index) + '" style="border-bottom:1px solid #f9f9f9;line-height:25px;color: #ff8200;"')
221 | html_content = html_content.replace('class="td-02"',
222 | 'class="td-02" style="border-bottom:1px solid #f9f9f9;line-height:25px;"')
223 | html_content = html_content.replace('class="td-03"',
224 | 'class="td-03" style="border-bottom:1px solid #f9f9f9;line-height:25px;"')
225 | html_content = html_content.replace('target="_blank"',
226 | 'target="_blank" style="text-decoration:none;color:#0078b6;"')
227 | html_content = html_content.replace('class="th-02"',
228 | 'class="th-02" style="width:1000px;min-width:1000px;"')
229 | html_content = html_content.replace('',
230 | ' |
| '
231 | '————————————————————————————'
232 | ' | |
')
233 | return html_content
234 |
235 |
236 | # screen_word_list = [
237 | # "流浪地球",
238 | # "刘德华",
239 | # "吴京",
240 | # "谢楠",
241 | # "郭帆"
242 | # ]
243 | # screen_type_list = [
244 | # # 'new',
245 | # # 'hot',
246 | # 'boil',
247 | # 'boom'
248 | # ]
249 | # hot_search_list = get_hot_search_list(False, screen_word_list, screen_type_list)
250 | # for hot_search_data in hot_search_list:
251 | # icon_str = hot_search_data['icon']
252 | # if icon_str is None:
253 | # print(hot_search_data['index'] + ": " + hot_search_data['title']
254 | # + "(" + hot_search_data['count'] + ") " + hot_search_data['url'])
255 | # else:
256 | # type_str = "新" if icon_str == "icon icon_new" else \
257 | # "热" if icon_str == "icon icon_hot" else \
258 | # "沸" if icon_str == "icon icon_boil" else "爆"
259 | # print(hot_search_data['index'] + ": " + hot_search_data['title']
260 | # + "(" + hot_search_data['count'] + ")"
261 | # + " " + type_str + " " + hot_search_data['url'])
262 |
--------------------------------------------------------------------------------