def check_auth(username, password): """This function is called to check if a username / password combination is valid. """ global APP_RESOURCE config = ConfigHelper(APP_RESOURCE) auth_username = config.get_property_by_section('server', 'auth.username') auth_password = config.get_property_by_section('server', 'auth.password') return username == auth_username and password == auth_password
def config_db_url(resource): config = ConfigHelper(resource) url = 'postgresql+psycopg2://{user}:{pw}@{host}:{port}/{db}'.format( db=config.get_property_by_section('datasource', 'inova.db.datasource'), host=config.get_property_by_section('datasource', 'inova.db.host'), port=config.get_property_by_section('datasource', 'inova.db.port'), user=config.get_property_by_section('datasource', 'inova.db.username'), pw=config.get_property_by_section('datasource', 'inova.db.password')) return url
def initialize_config(): path = os.path.dirname(os.path.realpath(__file__)) fileConfig(f"{path}/config/log.ini") # fileConfig('./config/log.ini') config = ConfigHelper() return { 'base_url': config.get('server', 'base_url'), 'port': config.get('server', 'port'), 'workers': config.get('server', 'workers'), 'log_level': config.get('logging', 'level') }
def __init__(self): config_helper = ConfigHelper() dialect = config_helper.get("database", "dialect") host = config_helper.get("database", "host") port = config_helper.get("database", "port") name = config_helper.get("database", "name") username = config_helper.get("database", "username") password = config_helper.get("database", "password") # TODO: I couldn't get MySQL to work without added pymysql to the connection string # SQLAlchemy uses mysqldb by default but I couldn't find that module in PyPi self._engine = create_engine( f"{dialect}+pymysql://{username}:{password}@{host}:{port}/{name}") self.session_factory = sessionmaker(bind=self._engine) self.session = scoped_session(self.session_factory)
def __init__(self, parent=None): super(TraySetting, self).__init__(parent) self.setupUi(self) # 初始化数据 self.__db_helper = DBHelper(self) self.__config_helper = ConfigHelper(self) self.__sql_where = self.__config_helper.get_config_key( self.__config_section_background, "sqlWhere") self.textEdit_sqlWhere.setText(self.__sql_where) self.__time_interval = int( self.__config_helper.get_config_key( self.__config_section_background, "timeIntervalInMin")) self.lineEdit_min.setText(str(self.__time_interval)) self.__current_image = None self.pushButton_save.pressed.connect(self.__save) self.pushButton_cancel.pressed.connect(self.hide) # 系统托盘 self.__tray = QtWidgets.QSystemTrayIcon() self.__tray.setIcon(QtGui.QIcon("images/tranIcon.png")) self.__tray.setToolTip("壁纸切换") self.__tray.activated[QSystemTrayIcon.ActivationReason].connect( self.__on_tray_click) menu = QtWidgets.QMenu() # 创建显示器对应壁纸项 self._monitors = get_monitors() self.__levels = self.__db_helper.get_model_data_list('level') self.create_monitor_menu(menu) # 壁纸切换方式 self.__change_type_actions = list() self.create_change_type_menu(menu) switch_next = QtWidgets.QAction("切换下一张", self) switch_next.triggered.connect(self.__change_background) menu.addAction(switch_next) # 加载默认参数 type_value = self.__config_helper.get_config_key( self.__config_section_background, self.__config_key_change_type, ChangeType.Order.value) self.__change_type = ChangeType(int(type_value)) self.__update_change_type_action(self.__change_type) offset = self.__config_helper.get_config_key( self.__config_section_background, self.__config_key_last_order_image_offset, 0) self.__last_order_image_offset = int(offset) menu.addSeparator() setting = QtWidgets.QAction("设置", self) setting.triggered.connect(self.show) menu.addAction(setting) close = QtWidgets.QAction("退出", self) close.triggered.connect(self.close) menu.addAction(close) self.__tray.setContextMenu(menu) self.__tray.show() threading.Thread(target=self.__change_windows_background_timely, daemon=True).start()
class TraySetting(QtWidgets.QWidget, Ui_TraySetting): __config_section_background = "background" __config_key_change_type = "changeType" __config_key_last_order_image_offset = "lastOrderImageOffset" _monitor_start_y = 0 _monitor_settings = [] # 显示器设定列表 def __init__(self, parent=None): super(TraySetting, self).__init__(parent) self.setupUi(self) # 初始化数据 self.__db_helper = DBHelper(self) self.__config_helper = ConfigHelper(self) self.__sql_where = self.__config_helper.get_config_key( self.__config_section_background, "sqlWhere") self.textEdit_sqlWhere.setText(self.__sql_where) self.__time_interval = int( self.__config_helper.get_config_key( self.__config_section_background, "timeIntervalInMin")) self.lineEdit_min.setText(str(self.__time_interval)) self.__current_image = None self.pushButton_save.pressed.connect(self.__save) self.pushButton_cancel.pressed.connect(self.hide) # 系统托盘 self.__tray = QtWidgets.QSystemTrayIcon() self.__tray.setIcon(QtGui.QIcon("images/tranIcon.png")) self.__tray.setToolTip("壁纸切换") self.__tray.activated[QSystemTrayIcon.ActivationReason].connect( self.__on_tray_click) menu = QtWidgets.QMenu() # 创建显示器对应壁纸项 self._monitors = get_monitors() self.__levels = self.__db_helper.get_model_data_list('level') self.create_monitor_menu(menu) # 壁纸切换方式 self.__change_type_actions = list() self.create_change_type_menu(menu) switch_next = QtWidgets.QAction("切换下一张", self) switch_next.triggered.connect(self.__change_background) menu.addAction(switch_next) # 加载默认参数 type_value = self.__config_helper.get_config_key( self.__config_section_background, self.__config_key_change_type, ChangeType.Order.value) self.__change_type = ChangeType(int(type_value)) self.__update_change_type_action(self.__change_type) offset = self.__config_helper.get_config_key( self.__config_section_background, self.__config_key_last_order_image_offset, 0) self.__last_order_image_offset = int(offset) menu.addSeparator() setting = QtWidgets.QAction("设置", self) setting.triggered.connect(self.show) menu.addAction(setting) close = QtWidgets.QAction("退出", self) close.triggered.connect(self.close) menu.addAction(close) self.__tray.setContextMenu(menu) self.__tray.show() threading.Thread(target=self.__change_windows_background_timely, daemon=True).start() def create_monitor_menu(self, menu): """ 创建多显示器的菜单项 :param menu: :return: """ start_y = 0 monitors = get_monitors() for i in range(len(monitors)): monitor = monitors[i] desc_action = QtWidgets.QAction("", self) desc_action.triggered.connect( partial(self.__open_file_in_directory_and_copy_file_name, i)) menu.addAction(desc_action) if monitor.width > monitor.height: screen_state = '横屏' else: screen_state = '竖屏' level_menu = menu.addMenu(f" {monitor.name} {screen_state} - 等级") level_actions = [] for level in self.__levels: level_action = level_menu.addAction(level.name) level_action.setCheckable(True) level_action.triggered.connect( partial(self.__set_level, i, level.id)) level_actions.append(level_action) menu.addSeparator() self._monitor_settings.append( MonitorSetting(monitor=monitor, image_desc_action=desc_action, image_level_actions=level_actions)) start_y = min(start_y, monitor.y) self._monitor_start_y = start_y def create_change_type_menu(self, menu): change_type_menu = menu.addMenu("切换方式") change_order = self.__create_type_action("顺序", ChangeType.Order) change_type_menu.addAction(change_order) self.__change_type_actions.append(change_order) change_random = self.__create_type_action("随机", ChangeType.Random) change_type_menu.addAction(change_random) self.__change_type_actions.append(change_random) def __create_type_action(self, name, change_type): action = QtWidgets.QAction(name, self) action.setCheckable(True) action.triggered.connect(partial(self.__set_change_type, change_type)) return action def __set_change_type(self, change_type: ChangeType): self.__change_type = change_type self.__update_change_type_action(change_type) def __update_change_type_action(self, change_type: ChangeType): if change_type == ChangeType.Order: self.__change_type_actions[0].setChecked(True) self.__change_type_actions[1].setChecked(False) elif change_type == ChangeType.Random: self.__change_type_actions[0].setChecked(False) self.__change_type_actions[1].setChecked(True) self.__config_helper.add_config_key(self.__config_section_background, self.__config_key_change_type, change_type.value) def __save(self): self.__sql_where = self.textEdit_sqlWhere.toPlainText() time_interval = self.lineEdit_min.text() self.__time_interval = int(time_interval) self.__config_helper.add_config_key("background", "sqlWhere", self.__sql_where) self.__config_helper.add_config_key("background", "timeIntervalInMin", time_interval) self.__last_order_image_offset = int(self.lineEdit_order_offset.text()) self.__config_helper.add_config_key( self.__config_section_background, self.__config_key_last_order_image_offset, self.__last_order_image_offset) self.hide() def __change_windows_background_timely(self): while True: sleep_second = self.__time_interval * 60 if self.__change_background(): time.sleep(sleep_second) def __change_background(self): """ 修改桌面壁纸 :return: """ images = [] start_y_list = [] for i in range(len(self._monitor_settings)): setting = self._monitor_settings[i] image, index, count = self._get_image( setting.monitor.width >= setting.monitor.height) if image and os.path.exists(image.path): setting.image = image desc = f"[{index}/{count}] {image.author} - {image.filename}" if len(desc) > 50: desc = f"{desc[0:46]}..." setting.image_desc_action.setText(desc) self.__update_level_action(i, image.level_id) image_data = ImageHelper.get_sized_image( image.path, width=setting.monitor.width, height=setting.monitor.height) if image_data: images.append(image_data) start_y_list.append(setting.monitor.y - self._monitor_start_y) final_image_name = "final.jpg" ImageHelper.merge_horizontal_img(images, start_y_list, final_image_name) if len(images) != len(self._monitor_settings): QMessageBox.information(self, "提示", "sql 语句限制过多,获取不到图片", QMessageBox.Ok) return False path = os.path.join(os.getcwd(), final_image_name) key = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, win32con.KEY_SET_VALUE) win32api.RegSetValueEx(key, "WallpaperStyle", 0, win32con.REG_SZ, "0") win32api.RegSetValueEx(key, "TileWallpaper", 0, win32con.REG_SZ, "1") win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, path, 1 + 2) return True def _get_image(self, is_horizontal): """ 从数据库获取下一张图片 :param is_horizontal: 是否是横图 :return: (图片信息,索引,总数) """ sql_where = self.__sql_where if is_horizontal: operator = '>=' else: operator = '<=' sql_where += f' and width{operator}height' image_count = self.__db_helper.get_image_count(sql_where) if self.__change_type == ChangeType.Order: offset = self.__get_order_offset(image_count) else: offset = random.randint(0, image_count) image = self.__db_helper.get_one_image_with_where(sql_where, offset) print( f'where: {sql_where}, id: {image.id}, width: {image.width}, height: {image.height}, path: {image.path}' ) return image, offset, image_count def __get_order_offset(self, image_count): """ 获取顺序切换时下一张图片的偏移量 :param image_count: 图片总数 :return: 偏移量 """ if self.__last_order_image_offset < image_count - 1: offset = self.__last_order_image_offset + 1 else: offset = 0 self.__last_order_image_offset = offset self.__config_helper.add_config_key( self.__config_section_background, self.__config_key_last_order_image_offset, self.__last_order_image_offset) if self.isHidden(): self.lineEdit_order_offset.setText(str(offset)) return offset def __update_level_action(self, index, level_id): """ 更新当前显示器壁纸等级状态 :param index: 显示器索引 :param level_id: 等级 id :return: """ level_actions = self._monitor_settings[index].image_level_actions for i in range(len(self.__levels)): level = self.__levels[i] level_actions[i].setChecked(level.id == level_id) def __on_tray_click(self, reason: QSystemTrayIcon.ActivationReason): if reason == QSystemTrayIcon.Trigger: self.show() return def __open_file_in_directory_and_copy_file_name(self, index): image = self._monitor_settings[index].image file_path = image.path.replace('/', '\\') ex = f"explorer /select,{file_path}" os.system(ex) pyperclip.copy(image.filename) def __set_level(self, index, level_id): image = self._monitor_settings[index].image image.level_id = level_id self.__db_helper.update_image(image) self.__update_level_action(index, level_id)
#!/usr/bin/env python3 # # This script will run the main application file in debug mode. # # author: Michael Gruber # # Adapted by Lucas Nadalete from sys import path import os.path path.append('src/main/python/') from helper.config_helper import ConfigHelper from webapp import application, APP_RESOURCE # Load server configuration helper = ConfigHelper(APP_RESOURCE) chost = helper.get_property_by_section('server', 'inova.host') cport = int(helper.get_property_by_section('server', 'inova.port')) cdebug = bool(helper.get_property_by_section('server', 'inova.debug')) # Start Web Server for all hosts, ssl_context=('cert.pem', 'key.pem') if __name__ == "__main__": application.run(host=chost, debug=cdebug, port=cport)
# '靠廢柴技能【狀態異常】.yaml', # '有點色公主殿下.yaml', # '和神獸在一起.yaml', # '創始魔法師.yaml', # '幸存煉金術師的城市慢活記.yaml', # '軍武宅轉開軍隊後宮.yaml' # '女兒已經升到了S級.yaml', # '田中~年齡等於單身資歷的魔法師~.yaml', # '世界最強後衛.yaml', # '鐵鏟無雙.yaml', '等級封頂的最強劍聖女碧翠斯也有弱點.yaml', # '因為不是真正的夥伴而被逐出勇者隊伍.yaml', # '勇者以想要成為朋友的視線看了過來!.yaml', # '孤單一人的異世界攻略.yaml', # '可以讀檔的旅店.yaml', ] for book_name in book_list: cwd = os.getcwd() config = ConfigHelper(config_name=book_name, config_path=os.path.join( cwd, 'books_yaml')).get_config() # print(config) books = config['book']['books'] book_info = config['book']['info'] for book in books: print(book[0], book[1]) main(book[0], book[1], book_info)
def __init__(self, parent=None): super(ImageManager, self).__init__(parent) self.setupUi(self) self.__db_helper = DBHelper(self.db_error_handler) # 数据库操作 # 下拉列表设置 self.__type_model = MyBaseListModel() self.comboBox_type.setModel(self.__type_model) self.__type_model.add_items(self.__db_helper.get_model_data_list('type')) self.comboBox_type.setCurrentIndex(0) self.__level_model = MyBaseListModel() self.comboBox_level.setModel(self.__level_model) levels = self.__db_helper.get_model_data_list('level') for i in range(len(levels)): level = levels[i] if level.id == 10: levels.remove(level) levels.insert(4, level) self.__level_model.add_items(levels) self.comboBox_level.setCurrentIndex(0) # 图片信息 self.__image_model = ImageFileListModel(self) self.__image_model.delete_repeat = self.checkBox_delete_repeat.isChecked() self.__config = ConfigHelper(self) threading.Thread(target=self._load_default_images, daemon=True).start() self.lineEdit_sql_where.setText(self.__config.get_config_key('history', 'sqlWhere')) self.lineEdit_export_dir.setText(self.__config.get_config_key('history', 'lastExportDir')) self.listView.setModel(self.__image_model) # 关联事件 self.listView.selectionModel().currentChanged.connect(self.__on_list_view_current_row_change) self.listView.set_key_press_delegate(self.key_press_delegate) self.listView.set_action_show_file_directory_delegate(self.open_file_directory) self.pushButton_classify.clicked.connect(self.__classify) self.pushButton_search.clicked.connect(self.__search) self.pushButton_clean.clicked.connect(self.__clean_not_exist_images) self.checkBox_delete_repeat.clicked.connect(self._on_check_box_delete_repeat_click) self.actionOpen.triggered.connect(self.__open_files) self.lineEdit_sql_where.returnPressed.connect(self.__search) self.pushButton_export_dir.clicked.connect(self.__choose_export_dir) self.pushButton_export.clicked.connect(self.__choose_export) self.lineEdit_desc.returnPressed.connect(self.__classify) self.lineEdit_tag.returnPressed.connect(self.__classify) self.lineEdit_role.returnPressed.connect(self.__classify) self.lineEdit_works.returnPressed.connect(self.__classify) self.lineEdit_series.returnPressed.connect(self.__classify) self.lineEdit_source.returnPressed.connect(self.__classify) self.lineEdit_uploader.returnPressed.connect(self.__classify) self.lineEdit_author.returnPressed.connect(self.__classify) self._signal_update_image_id.connect(self._update_image_id) # 设置 tab 切换顺序 self.setTabOrder(self.lineEdit_desc, self.lineEdit_tag) self.setTabOrder(self.lineEdit_tag, self.lineEdit_path) self.setTabOrder(self.lineEdit_path, self.comboBox_type) self.setTabOrder(self.comboBox_type, self.comboBox_level) self.setTabOrder(self.comboBox_level, self.lineEdit_role) self.setTabOrder(self.lineEdit_role, self.lineEdit_works) self.setTabOrder(self.lineEdit_works, self.lineEdit_series) self.setTabOrder(self.lineEdit_series, self.lineEdit_source) self.setTabOrder(self.lineEdit_source, self.lineEdit_uploader) self.setTabOrder(self.lineEdit_uploader, self.lineEdit_author) self.setTabOrder(self.lineEdit_author, self.pushButton_classify) self.setTabOrder(self.pushButton_classify, self.pushButton_search) # 自动补全 self.__completer_list = [] self.__completer_filename = 'works.txt' if not os.path.exists(self.__completer_filename): f = open(self.__completer_filename, 'w', encoding='utf-8') f.close() with open(self.__completer_filename, 'r+', encoding='utf-8') as f: self.__completer_list = list(map(lambda x: x.replace("\n", "").replace("\r", ""), f.readlines())) self.completer = QCompleter(self.__completer_list) self.completer.setCompletionMode(QCompleter.InlineCompletion) self.completer.setFilterMode(Qt.MatchContains) self.lineEdit_works.setCompleter(self.completer) self.lineEdit_works.editingFinished.connect(self.__add_complete) # Image.MAX_IMAGE_PIXELS = 1882320000 self.listView.setFocus() # 预加载图片 threading.Thread(target=self.__preload, daemon=True).start()
class ImageManager(QMainWindow, Ui_Manager): _signal_update_image_id = pyqtSignal(QModelIndex, int) def __init__(self, parent=None): super(ImageManager, self).__init__(parent) self.setupUi(self) self.__db_helper = DBHelper(self.db_error_handler) # 数据库操作 # 下拉列表设置 self.__type_model = MyBaseListModel() self.comboBox_type.setModel(self.__type_model) self.__type_model.add_items(self.__db_helper.get_model_data_list('type')) self.comboBox_type.setCurrentIndex(0) self.__level_model = MyBaseListModel() self.comboBox_level.setModel(self.__level_model) levels = self.__db_helper.get_model_data_list('level') for i in range(len(levels)): level = levels[i] if level.id == 10: levels.remove(level) levels.insert(4, level) self.__level_model.add_items(levels) self.comboBox_level.setCurrentIndex(0) # 图片信息 self.__image_model = ImageFileListModel(self) self.__image_model.delete_repeat = self.checkBox_delete_repeat.isChecked() self.__config = ConfigHelper(self) threading.Thread(target=self._load_default_images, daemon=True).start() self.lineEdit_sql_where.setText(self.__config.get_config_key('history', 'sqlWhere')) self.lineEdit_export_dir.setText(self.__config.get_config_key('history', 'lastExportDir')) self.listView.setModel(self.__image_model) # 关联事件 self.listView.selectionModel().currentChanged.connect(self.__on_list_view_current_row_change) self.listView.set_key_press_delegate(self.key_press_delegate) self.listView.set_action_show_file_directory_delegate(self.open_file_directory) self.pushButton_classify.clicked.connect(self.__classify) self.pushButton_search.clicked.connect(self.__search) self.pushButton_clean.clicked.connect(self.__clean_not_exist_images) self.checkBox_delete_repeat.clicked.connect(self._on_check_box_delete_repeat_click) self.actionOpen.triggered.connect(self.__open_files) self.lineEdit_sql_where.returnPressed.connect(self.__search) self.pushButton_export_dir.clicked.connect(self.__choose_export_dir) self.pushButton_export.clicked.connect(self.__choose_export) self.lineEdit_desc.returnPressed.connect(self.__classify) self.lineEdit_tag.returnPressed.connect(self.__classify) self.lineEdit_role.returnPressed.connect(self.__classify) self.lineEdit_works.returnPressed.connect(self.__classify) self.lineEdit_series.returnPressed.connect(self.__classify) self.lineEdit_source.returnPressed.connect(self.__classify) self.lineEdit_uploader.returnPressed.connect(self.__classify) self.lineEdit_author.returnPressed.connect(self.__classify) self._signal_update_image_id.connect(self._update_image_id) # 设置 tab 切换顺序 self.setTabOrder(self.lineEdit_desc, self.lineEdit_tag) self.setTabOrder(self.lineEdit_tag, self.lineEdit_path) self.setTabOrder(self.lineEdit_path, self.comboBox_type) self.setTabOrder(self.comboBox_type, self.comboBox_level) self.setTabOrder(self.comboBox_level, self.lineEdit_role) self.setTabOrder(self.lineEdit_role, self.lineEdit_works) self.setTabOrder(self.lineEdit_works, self.lineEdit_series) self.setTabOrder(self.lineEdit_series, self.lineEdit_source) self.setTabOrder(self.lineEdit_source, self.lineEdit_uploader) self.setTabOrder(self.lineEdit_uploader, self.lineEdit_author) self.setTabOrder(self.lineEdit_author, self.pushButton_classify) self.setTabOrder(self.pushButton_classify, self.pushButton_search) # 自动补全 self.__completer_list = [] self.__completer_filename = 'works.txt' if not os.path.exists(self.__completer_filename): f = open(self.__completer_filename, 'w', encoding='utf-8') f.close() with open(self.__completer_filename, 'r+', encoding='utf-8') as f: self.__completer_list = list(map(lambda x: x.replace("\n", "").replace("\r", ""), f.readlines())) self.completer = QCompleter(self.__completer_list) self.completer.setCompletionMode(QCompleter.InlineCompletion) self.completer.setFilterMode(Qt.MatchContains) self.lineEdit_works.setCompleter(self.completer) self.lineEdit_works.editingFinished.connect(self.__add_complete) # Image.MAX_IMAGE_PIXELS = 1882320000 self.listView.setFocus() # 预加载图片 threading.Thread(target=self.__preload, daemon=True).start() def __add_complete(self): """ 添加自动补全作品 :return: """ cur_completion = self.completer.currentCompletion() if cur_completion == "": self.__completer_list.append(self.lineEdit_works.text()) self.completer = QCompleter(self.__completer_list) self.completer.setCompletionMode(QCompleter.InlineCompletion) self.completer.setFilterMode(Qt.MatchContains) self.lineEdit_works.setCompleter(self.completer) print(self.__completer_list) def _load_default_images(self): last_dir = self.__config.get_config_key('history', 'lastDir') if os.path.isdir(last_dir) and os.path.exists(last_dir): self.__image_model.add_path(last_dir) if self.__image_model.rowCount() > 0: self.listView.setCurrentIndex(self.__image_model.index(0, 0)) def __open_files(self): """ 打开图片文件 :return: """ path_list = \ QtWidgets.QFileDialog.getOpenFileNames(self, "选择文件", filter='图片(*.jpg *.png *.gif *.jpeg *.bmp)')[0] # 生成List使用的Model for path in path_list: tp_lists = path.split('/') item_data = ImageFile( name="%s/%s" % (tp_lists[-2], tp_lists[-1]), full_path=path ) self.__image_model.addItem(item_data) def __choose_export_dir(self): """ 选择保存文件夹 :return: """ dir_path = QtWidgets.QFileDialog.getExistingDirectory(self, "选择保存的文件夹", "E:/图片") self.lineEdit_export_dir.setText(dir_path) def __show_image(self, index): """ 显示指定索引文件名对应的图片 :param index: 文件索引 :return: """ path = self.__image_model.get_item(index).full_path start_time = time.time() status = f"[{index + 1}/{self.__image_model.rowCount()}] {path}" try: # 填充缩放 pixmap, is_preload = self.__get_image(path) cur_time = time.time() status += f"\t是否预加载:{is_preload}\t图片读取:${round((cur_time - start_time) * 1000, 2)}ms" start_time = time.time() # 加载图片 item = QtWidgets.QGraphicsPixmapItem(pixmap) scene = QtWidgets.QGraphicsScene() scene.addItem(item) self.graphicsView.setScene(scene) cur_time = time.time() status += f"\t图片加载:${round((cur_time - start_time) * 1000, 2)}ms" except Exception as e: print(e) QMessageBox.information(self, "提示", str(e), QMessageBox.Ok) self.__analysis_file_info(path) self.statusbar.showMessage(status) def __on_list_view_current_row_change(self, current: QModelIndex, previous: QModelIndex): """ 图片列表当前行变化事件 :param current: 当前行索引 :param previous: :return: """ self.__show_image(current.row()) def __analysis_file_info(self, path): info = self.__db_helper.search_by_file_path(path) if not info: # 分析图片信息 self.lineEdit_path.setText(path) info = ImageHelper.analyze_image_info(path) self.lineEdit_size.setText(f"{info.size} MB") self.dateTimeEdit_file_create.setDateTime(info.create_time) self.lineEdit_desc.setText(info.desc) self.lineEdit_tag.setText(info.tags) if info.source: self.lineEdit_source.setText(info.source) if info.uploader: self.lineEdit_uploader.setText(info.uploader) if info.author: self.lineEdit_author.setText(info.author) return # 显示已有记录 self.lineEdit_desc.setText(info.desc) self.lineEdit_tag.setText(info.tags) self.lineEdit_path.setText(info.path) self.lineEdit_works.setText(info.works) self.lineEdit_source.setText(info.source) self.lineEdit_role.setText(info.role) self.lineEdit_author.setText(info.author) self.lineEdit_series.setText(info.series) self.lineEdit_uploader.setText(info.uploader) self.lineEdit_size.setText(f"{info.size} MB") self.comboBox_type.setCurrentIndex(self.__type_model.get_index(info.type_id)) self.comboBox_level.setCurrentIndex(self.__level_model.get_index(info.level_id)) self.dateTimeEdit_file_create.setDateTime(info.file_create_time) self.dateTimeEdit_create.setDateTime(info.create_time) self.dateTimeEdit_update.setDateTime(info.update_time) def __classify(self): """ 分类图片 :return: """ select_rows = self.listView.selectionModel().selectedRows() select_rows = [x for x in select_rows] th = threading.Thread(target=self.__insert_or_update_db, args=(select_rows,), daemon=True) th.start() end_index = select_rows[-1] self.__select_index(self.__image_model.index(end_index.row() + 1, end_index.column())) def __insert_or_update_db(self, select_rows): index = self.comboBox_type.currentIndex() type_id = self.__type_model.get_item(index).id index = self.comboBox_level.currentIndex() level_id = self.__level_model.get_item(index).id desc = self.lineEdit_desc.text() author = self.lineEdit_author.text() tags = self.lineEdit_tag.text() works = self.lineEdit_works.text() role = self.lineEdit_role.text() source = self.lineEdit_source.text() series = self.lineEdit_series.text() uploader = self.lineEdit_uploader.text() for i in range(len(select_rows)): item = self.__image_model.get_item(select_rows[i].row()) path = item.full_path image = MyImage(id=item.id, desc=desc, author=author, type_id=type_id, level_id=level_id, tags=tags, works=works, role=role, source=source, width=self.lineEdit_width.text(), height=self.lineEdit_height.text(), size=FileHelper.get_file_size_in_mb(path), filename=item.name, path=path, md5=FileHelper.get_md5(path), file_create_time=FileHelper.get_create_time_str(path), series=series, uploader=uploader) if image.id == 0: self.__db_helper.insert_image(image) image_id = self.__db_helper.get_id_by_path(path) self._signal_update_image_id.emit(select_rows[i], image_id) self.dateTimeEdit_create.setDateTime(datetime.datetime.now()) self.dateTimeEdit_update.setDateTime(datetime.datetime.now()) # message = f"{item.name} 创建完成!" else: # 批量更新时,保持原来的描述、作者、等级、标签、作品 old_image = self.__image_model.get_database_item(image.id) if old_image and len(select_rows) > 1: image.desc = old_image.desc image.author = old_image.author image.level_id = old_image.level_id image.tags = old_image.tags image.works = old_image.works self.__db_helper.update_image(image) self.dateTimeEdit_update.setDateTime(datetime.datetime.now()) message = f"{item.name} 更新完成!" self.statusbar.showMessage(f"[{i + 1}/{len(select_rows)}] {message}") # end_index = select_rows[-1] def _update_image_id(self, index: QModelIndex, image_id: int): self.__image_model.set_image_id(index,image_id) def __select_index(self, index: QModelIndex): if 0 < index.row() < self.__image_model.rowCount(): self.listView.setCurrentIndex(index) self.listView.setFocus() else: self.listView.clearFocus() self.listView.setFocus() def __del_select_rows(self): """ 删除选中行 :return: """ select_rows = self.listView.selectionModel().selectedRows() if len(select_rows) == 0: return first_index = select_rows[0] for i in range(len(select_rows)): index = select_rows[i] item = self.__image_model.get_item(index.row() - i) if item.id != 0: self.__db_helper.delete(item.id) os.remove(item.full_path) self.__image_model.delete_item(index.row() - i) self.statusbar.showMessage(f"[{i + 1}/{len(select_rows)}] {item.name} 删除成功!") if len(select_rows) > 1: self.listView.clearSelection() # 如果删除到了最后一行,则刷新上一个 if first_index.row() >= self.__image_model.rowCount(): if first_index.row() == 0: return else: self.listView.setCurrentIndex(self.listView.model().index(first_index.row() - 1, first_index.column())) else: if len(select_rows) > 1: self.listView.setCurrentIndex(first_index) else: self.__show_image(first_index.row()) def __search(self): sql_where = self.lineEdit_sql_where.text() if not sql_where: sql_where = "" if len(self.lineEdit_desc.text()): sql_where += f" `desc` like '%{self.lineEdit_desc.text()}%'" if len(self.lineEdit_role.text()): sql_where += f" `role` like '%{self.lineEdit_role.text()}%'" if len(self.lineEdit_works.text()): sql_where += f" `works` like '%{self.lineEdit_works.text()}%'" if len(self.lineEdit_series.text()): sql_where += f" `series` like '%{self.lineEdit_series.text()}%'" if len(self.lineEdit_source.text()): sql_where += f" `source` like '%{self.lineEdit_source.text()}%'" if len(self.lineEdit_uploader.text()): sql_where += f" `uploader` like '%{self.lineEdit_uploader.text()}%'" if len(self.lineEdit_author.text()): sql_where += f" `author` like '%{self.lineEdit_author.text()}%'" image_sql_list, image_file_list = self.__db_helper.search_by_where(sql_where) if len(image_sql_list) > 0: self.__image_model.set_images(image_sql_list, image_file_list) self.listView.setFocus() self.listView.scrollToTop() def __choose_export(self): dir_path = self.lineEdit_export_dir.text() if not os.path.exists(dir_path): os.makedirs(dir_path) if not os.path.isdir(dir_path): return for i in range(self.__image_model.rowCount()): image = self.__image_model.get_item(i) if image.id: image_sql = self.__image_model.get_database_item(image.id) if not os.path.exists(image_sql.path): continue try: FileHelper.copyfile_without_override(image_sql.path, dir_path) except Exception as e: print(e) else: FileHelper.copyfile_without_override(image.full_path, dir_path) self.statusbar.showMessage(f"[{i + 1}/{self.__image_model.rowCount()}] {image.name} 复制成功!") def _on_check_box_delete_repeat_click(self): print(f'是否删除重复:{self.checkBox_delete_repeat.isChecked()}') self.__image_model.delete_repeat = self.checkBox_delete_repeat.isChecked() # region 重写 Qt 控件方法 def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: # 键盘快捷键事件 if event.key() == Qt.Key_R and QApplication.keyboardModifiers() == Qt.ControlModifier: self.__classify() self.listView.setFocus() if event.key() == Qt.Key_E and QApplication.keyboardModifiers() == Qt.ControlModifier: self.comboBox_level.setFocus() if event.key() == Qt.Key_W and QApplication.keyboardModifiers() == Qt.ControlModifier: self.lineEdit_works.setText("") # if event.key() == Qt.Key_Delete: # self.__del_select_rows() def key_press_delegate(self, event: QtGui.QKeyEvent): level_index = None if event.key() == Qt.Key_1: level_index = 1 if event.key() == Qt.Key_2: level_index = 2 if event.key() == Qt.Key_3: level_index = 3 if event.key() == Qt.Key_4: level_index = 4 if event.key() == Qt.Key_5: level_index = 5 if event.key() == Qt.Key_6: level_index = 6 if event.key() == Qt.Key_7: level_index = 7 if event.key() == Qt.Key_8: level_index = 8 if event.key() == Qt.Key_9: level_index = 9 if level_index and self.__level_model.rowCount() >= level_index: self.comboBox_level.setCurrentIndex(level_index - 1) return True if event.key() == Qt.Key_R: self.__classify() return True if event.key() == Qt.Key_E: self.lineEdit_role.setFocus() return True if event.key() == Qt.Key_C: self.lineEdit_works.setText("") return True if event.key() == Qt.Key_D: self.__del_select_rows() return True if event.key() == Qt.Key_W: current_index = self.listView.currentIndex() if current_index.row() > 0: self.listView.setCurrentIndex(self.__image_model.index(current_index.row() - 1, current_index.column())) return True if event.key() == Qt.Key_S: current_index = self.listView.currentIndex() if current_index.row() < self.__image_model.rowCount() - 1: self.listView.setCurrentIndex(self.__image_model.index(current_index.row() + 1, current_index.column())) return True return False def dragEnterEvent(self, e: QtGui.QDragEnterEvent) -> None: # 设置允许接收 e.accept() def dropEvent(self, e: QtGui.QDropEvent) -> None: # 接收文件夹和文件以刷新图片列表 urls = e.mimeData().urls() th = threading.Thread(target=self.__load_list_data, args=(urls,), daemon=True) th.start() def __load_list_data(self, urls): self.__image_model.clear() for url in urls: self.__image_model.add_path(url.toLocalFile()) if self.__image_model.rowCount() > 0: self.listView.setCurrentIndex(self.__image_model.index(0, 0)) if not os.path.isdir(urls[0].toLocalFile()): return self.__config.add_config_key('history', 'lastDir', urls[0].toLocalFile()) def closeEvent(self, event: QtGui.QCloseEvent) -> None: self.__config.add_config_key('history', 'lastExportDir', self.lineEdit_export_dir.text()) self.__config.add_config_key('history', 'sqlWhere', self.lineEdit_sql_where.text()) # 关闭时保存自动填充作品列表的配置文件 with open(self.__completer_filename, 'w+', encoding='utf-8') as f: f.writelines(list(map(lambda x: x + "\n", self.__completer_list))) # endregion # region 预加载图片 __preload_count = 5 __preload_image_queue = queue.Queue(__preload_count) __preload_image_size = queue.Queue(__preload_count) __preload_lock = threading.Lock() def __preload(self): while True: if self.__preload_image_queue.qsize() == 5: time.sleep(1) continue index = self.listView.currentIndex().row() preload_index = index + self.__preload_image_queue.qsize() + 1 image_file = self.__image_model.get_item(preload_index) if not image_file: time.sleep(1) continue full_path = image_file.full_path try: pixmap, width, height = ImageHelper.get_image_from_file(full_path, self.graphicsView.width(), self.graphicsView.height()) self.__preload_image_queue.put(PreloadImage(full_path, pixmap)) self.__preload_image_size.put((width, height)) print(f"预加载成功:{full_path}") except Exception as e: print(e) print(f"预加载失败:{full_path}") time.sleep(1) def __get_image(self, path): # 优先从队列中获取 while self.__preload_image_queue.qsize() > 0: image = self.__preload_image_queue.get() size = self.__preload_image_size.get() if isinstance(image, PreloadImage) and image.full_path == path: print("从预载中读取") self.lineEdit_width.setText(str(size[0])) self.lineEdit_height.setText(str(size[1])) return image.pixmap, True print("从文件中读取") image, width, height = ImageHelper.get_image_from_file(path, self.graphicsView.width(), self.graphicsView.height()) self.lineEdit_width.setText(str(width)) self.lineEdit_height.setText(str(height)) return image, False # endregion def __clean_not_exist_images(self): """ 清理不存在的图片 :return: """ th = threading.Thread( target=ImageHelper.refresh_recode_info, args=(self.db_error_handler,self.show_status_message,), daemon=True ) th.start() def show_status_message(self, message): self.statusbar.showMessage(message) def open_file_directory(self): """ 打开文件所在目录并选中文件 :return: """ select_rows = self.listView.selectionModel().selectedRows() if not len(select_rows): return file_path = self.__image_model.get_item(select_rows[0].row()).full_path FileHelper.open_file_directory(file_path) def db_error_handler(self, error_str): QMessageBox.information(self, "提示", error_str, QMessageBox.Ok)