class NotificationsDialog(object): def __init__(self, parent, parent_window, notifications, dp=None): self._dialog = QDialog(parent_window) self._dp = dp self._notifications = notifications self._parent = parent self._parent_window = parent_window self._dialog.setWindowIcon(QIcon(':/images/icon.png')) self._ui = Ui_Dialog() self._ui.setupUi(self._dialog) self._init_ui() def _init_ui(self): self._dialog.setWindowFlags(Qt.Dialog) self._dialog.setAttribute(Qt.WA_TranslucentBackground) self._dialog.setAttribute(Qt.WA_MacFrameworkScaled) self._notifications_list = NotificationsList(self._dp) self._ui.notifications_area.setWidget(self._notifications_list) self._ui.notifications_area.verticalScrollBar().valueChanged.connect( self._on_list_scroll_changed) self._old_main_resize_event = self._ui.centralwidget.resizeEvent self._ui.centralwidget.resizeEvent = self._main_resize_event self._loader_movie = QMovie(":/images/loader.gif") self._ui.loader_label.setMovie(self._loader_movie) def show(self, on_finished): def finished(): self.show_cursor_normal() self._dialog.finished.disconnect(finished) on_finished() logger.debug("Opening notifications dialog") screen_width = QApplication.desktop().width() parent_x = self._dialog.parent().x() parent_width = self._dialog.parent().width() width = self._dialog.width() offset = 16 if parent_x + parent_width / 2 > screen_width / 2: x = parent_x - width - offset if x < 0: x = 0 else: x = parent_x + parent_width + offset diff = x + width - screen_width if diff > 0: x -= diff self._dialog.move(x, self._dialog.parent().y()) # Execute dialog self._dialog.finished.connect(finished) if not self._parent.load_notifications(show_loading=True): self.show_notifications() self._dialog.raise_() self._dialog.show() def raise_dialog(self): self._dialog.raise_() def close(self): self._dialog.reject() def show_cursor_loading(self, show_movie=False): if show_movie: self._ui.notifications_pages.setCurrentIndex(2) self._loader_movie.start() else: self._dialog.setCursor(Qt.WaitCursor) self._parent_window.setCursor(Qt.WaitCursor) def show_cursor_normal(self): self._dialog.setCursor(Qt.ArrowCursor) self._parent_window.setCursor(Qt.ArrowCursor) if self._loader_movie.state() == QMovie.Running: self._loader_movie.stop() def show_notifications(self): if not self._notifications: self._ui.notifications_pages.setCurrentIndex(1) else: self._ui.notifications_pages.setCurrentIndex(0) self._notifications_list.show_notifications(self._notifications) self.show_cursor_normal() def _on_list_scroll_changed(self, *args, **kwargs): # value = self._ui.notifications_area.verticalScrollBar().value() # logger.debug("Scroll value %s", value) if self._parent.all_loaded or self._parent.is_querying: return if self._notifications_list.loading_needed(self._parent.limit): logger.debug("Loading notifications") self._parent.load_notifications() def _main_resize_event(self, e): self._old_main_resize_event(e) self._notifications_list.setFixedWidth( self._ui.notifications_pages.width() - 8) self._on_list_scroll_changed()
class CollaborationSettingsDialog(object): ADD_BUTTON_ACTIVE_COLOR = "#f78d1e" ADD_BUTTON_PASSIVE_COLOR = "#9a9a9a" ERROR_COLOR = '#FF9999' LINE_EDIT_NORMAL_COLOR = "#EFEFF1" def __init__(self, parent, parent_window, colleagues, folder, dp): self._dialog = QDialog(parent_window) self._dp = dp self._colleagues = colleagues self._parent = parent self._parent_window = parent_window self._folder = folder self._is_owner = False self._dialog.setWindowIcon(QIcon(':/images/icon.png')) self._ui = Ui_Dialog() self._ui.setupUi(self._dialog) self._init_ui() def _init_ui(self): self._dialog.setWindowFlags(Qt.Dialog) self._dialog.setAttribute(Qt.WA_TranslucentBackground) self._dialog.setAttribute(Qt.WA_MacFrameworkScaled) self._dialog.setWindowTitle(self._dialog.windowTitle() + self._folder) self._ui.colleagues_list.setAlternatingRowColors(True) self._colleagues_list = ColleaguesList(self._parent, self._ui.colleagues_list, self._dp, self._show_menu) self._loader_movie = QMovie(":/images/loader.gif") self._ui.loader_label.setMovie(self._loader_movie) self._set_fonts() self._ui.add_frame.setVisible(False) self._set_add_button_background(self.ADD_BUTTON_PASSIVE_COLOR) self._ui.add_button.clicked.connect(self._on_add_button_clicked) self._ui.add_button.setVisible(False) self._ui.close_button.clicked.connect(self._on_close_button_clicked) self._ui.refresh_button.clicked.connect(self._on_refresh) self._line_edit_style = "background-color: {};" self._ui.error_label.setStyleSheet("color: {};".format( self.ERROR_COLOR)) def _set_fonts(self): ui = self._ui controls = [ ui.colleagues_label, ui.mail_edit, ui.edit_radio, ui.view_radio, ui.add_button ] for control in controls: font = control.font() font_size = control.font().pointSize() * self._dp if font_size > 0: control_font = QFont(font.family(), font_size) control_font.setBold(font.bold()) control.setFont(control_font) def show(self): logger.debug("Opening collaboration settings dialog") screen_width = QApplication.desktop().width() parent_x = self._dialog.parent().x() parent_width = self._dialog.parent().width() width = self._dialog.width() offset = 16 if parent_x + parent_width / 2 > screen_width / 2: x = parent_x - width - offset if x < 0: x = 0 else: x = parent_x + parent_width + offset diff = x + width - screen_width if diff > 0: x -= diff self._dialog.move(x, self._dialog.parent().y()) # Execute dialog self._dialog.raise_() self.show_cursor_loading(True) self._dialog.exec_() def close(self): self._dialog.reject() def show_cursor_loading(self, show_movie=False): if show_movie: self._ui.stackedWidget.setCurrentIndex(1) self._loader_movie.start() else: self._dialog.setCursor(Qt.WaitCursor) self._parent_window.setCursor(Qt.WaitCursor) def show_cursor_normal(self): self._dialog.setCursor(Qt.ArrowCursor) self._parent_window.setCursor(Qt.ArrowCursor) if self._loader_movie.state() == QMovie.Running: self._loader_movie.stop() def show_colleagues(self): if not self._colleagues: self._ui.stackedWidget.setCurrentIndex(2) else: self._ui.stackedWidget.setCurrentIndex(0) self._colleagues_list.show_colleagues(self._colleagues) self.show_cursor_normal() def set_owner(self, is_owner): self._is_owner = is_owner self._ui.add_button.setVisible(self._is_owner) def _on_add_button_clicked(self): if self._ui.add_frame.isVisible(): if not self._validate_email(): return to_edit = self._ui.edit_radio.isChecked() self._ui.add_frame.setVisible(False) self._set_add_button_background(self.ADD_BUTTON_PASSIVE_COLOR) self._parent.add_colleague(self._ui.mail_edit.text(), to_edit) else: self._ui.add_frame.setVisible(True) self._set_add_button_background(self.ADD_BUTTON_ACTIVE_COLOR) self._ui.mail_edit.setText("") def _set_add_button_background(self, color): self._ui.add_button.setStyleSheet( 'background-color: {}; color: #fff; ' 'border-radius: 4px; font: bold "Gargi"'.format(color)) def _on_close_button_clicked(self): self._ui.add_frame.setVisible(False) self._set_add_button_background(self.ADD_BUTTON_PASSIVE_COLOR) self._clear_error() self._ui.mail_edit.setText("") def _validate_email(self): email_control = self._ui.mail_edit email_control.setStyleSheet( self._line_edit_style.format(self.LINE_EDIT_NORMAL_COLOR)) regex = '^.+@.{2,}$' email_control.setText(email_control.text().strip()) if not re.match(regex, email_control.text()): self._ui.error_label.setText(tr("Please enter a valid e-mail")) email_control.setStyleSheet( self._line_edit_style.format(self.ERROR_COLOR)) email_control.setFocus() return False self._clear_error() return True def _clear_error(self): self._ui.error_label.setText("") self._ui.mail_edit.setStyleSheet( self._line_edit_style.format(self.LINE_EDIT_NORMAL_COLOR)) def _on_refresh(self): self.show_cursor_loading() self._parent.query_collaboration_info() def _show_menu(self, colleague, pos): if not self._is_owner and not colleague.is_you or colleague.is_deleting: return menu = QMenu(self._ui.colleagues_list) menu.setStyleSheet("background-color: #EFEFF4; ") if colleague.is_you: if colleague.is_owner: action = menu.addAction(tr("Quit collaboration")) action.triggered.connect(self._on_quit_collaboration) else: action = menu.addAction(tr("Leave collaboration")) action.triggered.connect(self._on_leave_collaboration) else: rights_group = QActionGroup(menu) rights_group.setExclusive(True) menu.addSection(tr("Access rights")) action = menu.addAction(tr("Can view")) action.setCheckable(True) rights_action = rights_group.addAction(action) rights_action.setData(False) rights_action.setChecked(not colleague.can_edit) action = menu.addAction(tr("Can edit")) action.setCheckable(True) rights_action = rights_group.addAction(action) rights_action.setChecked(colleague.can_edit) rights_action.setData(True) rights_group.triggered.connect( lambda a: self._on_grant_edit(colleague, a)) menu.addSeparator() action = menu.addAction(tr("Remove user")) action.triggered.connect(lambda: self._on_remove_user(colleague)) pos_to_show = QPoint(pos.x(), pos.y() + 10) menu.exec_(pos_to_show) def _on_quit_collaboration(self): alert_str = "Collaboration will be cancelled, " \ "collaboration folder will be deleted " \ "from all colleagues' Pvtbox secured sync folders " \ "on all nodes." if self._user_confirmed_action(alert_str): self._parent.cancel_collaboration() def _on_leave_collaboration(self): alert_str = "Collaboration folder will be deleted " \ "from Pvtbox secured sync folders " \ "on all your nodes." if self._user_confirmed_action(alert_str): self._parent.leave_collaboration() def _on_remove_user(self, colleague): alert_str = "Colleague {} will be removed from collaboration. " \ "Collaboration folder will be deleted from colleague's " \ "Pvtbox secured sync folders on all nodes." \ .format(colleague.email) if self._user_confirmed_action(alert_str): self._parent.remove(colleague.id) def _on_grant_edit(self, colleague, action): to_edit = action.data() self._parent.grant_edit(colleague.id, to_edit) def _user_confirmed_action(self, alert_str): msg = tr("<b>Are</b> you <b>sure</b>?<br><br>{}".format(alert_str)) user_answer = msgbox(msg, title=' ', buttons=[ (tr('Cancel'), 'Cancel'), (tr('Yes'), 'Yes'), ], parent=self._dialog, default_index=0, enable_close_button=True) return user_answer == 'Yes'
class ADBHelper(object): # 构造函数 def __init__(self): # 加载UI文件 self.ui = QUiLoader().load('adbwindow.ui') # 设置窗口背景 palette = QPalette() pix = QPixmap('bg.jpg') #pix = pix.scaled(self.ui.width(), self.ui.height()) palette.setBrush(self.ui.backgroundRole(), QBrush(pix)) self.ui.setAutoFillBackground(True) self.ui.setPalette(palette) self.ui.setWindowIcon(QIcon('adb.png')) # self.ui.setWindowFlags(qcore.Qt.WindowStaysOnTopHint) # 绑定保存参数菜单项点击事件 self.ui.save_action.triggered.connect(self.save_params) # 绑定加载参数菜单项点击事件 self.ui.load_action.triggered.connect(self.load_params) # 绑定退出菜单项点击事件 self.ui.exit_action.triggered.connect(self.exit) # 绑定断开连接菜单项点击事件 self.ui.disconnect_action.triggered.connect(self.disconnect) # 绑定清空输出信息菜单项点击事件 self.ui.clear_action.triggered.connect(self.clear) # 绑定坐标工具菜单项点击事件 self.ui.tool_action.triggered.connect(self.tool) # 绑定关于菜单项点击事件 self.ui.about_action.triggered.connect(self.about) # 绑定启动ADB按钮点击事件 self.ui.openadb_pushButton.clicked.connect(self.open_adb) # 绑定连接按钮点击事件 self.ui.connect_pushButton.clicked.connect(self.connect) # 绑定显示设备列表按钮点击事件 self.ui.show_devices_pushButton.clicked.connect(self.show_devices) # 绑定开始点击按钮点击事件 self.ui.tap_pushButton.clicked.connect(self.tap) # 绑定开始滑屏按钮点击事件 self.ui.swipe_pushButton.clicked.connect(self.swipe) # 绑定停止按钮点击事件 self.ui.stop_pushButton.clicked.connect(self.stop) # 绑定坐标工具按钮点击事件 self.ui.tool_pushButton.clicked.connect(self.tool) # 限制数值范围 self.ui.swipe_x1_min_spinBox.valueChanged.connect(self.x1_min) self.ui.swipe_x1_max_spinBox.valueChanged.connect(self.x1_max) self.ui.swipe_y1_min_spinBox.valueChanged.connect(self.y1_min) self.ui.swipe_y1_max_spinBox.valueChanged.connect(self.y1_max) self.ui.swipe_x2_min_spinBox.valueChanged.connect(self.x2_min) self.ui.swipe_x2_max_spinBox.valueChanged.connect(self.x2_max) self.ui.swipe_y2_min_spinBox.valueChanged.connect(self.y2_min) self.ui.swipe_y2_max_spinBox.valueChanged.connect(self.y2_max) # ADB工具 self.adbtool = None # 连接标志 self.connected = False # 坐标工具窗口 self.tool_dialog = None # 截图文件 self.screen_cap_file = None # 当前时间 def nowtime(self): return str( _time.strftime('%Y-%m-%d %H:%M:%S', _time.localtime(_time.time()))) # 输出信息 def output_message(self, message): mess = "<font color='orange'>[</font><font color='blue'>"+self.nowtime() + \ "</font><font color='orange'>]</font><font color='green'>"+message+"</font>" self.ui.output_textEdit.append(mess) # 移动光标到最底 self.ui.output_textEdit.moveCursor(QTextCursor.End) # 输出结果和错误信息 def output_result_error(self, result, error): # 输出信息 self.output_message(result) # 判断错误信息是否为空 if len(error.strip()) != 0: self.output_message(error) # 保存参数 def save_params(self): # 弹出文件选择器 filepath, filetype = QFileDialog.getSaveFileName( self.ui, "保存参数", os.getcwd(), "Json File (*.json)") # 判断 if filepath != "": # IP地址 ip = self.ui.ip_lineEdit.text() # 端口号 port = self.ui.port_spinBox.value() # 模拟点击 tap_x = self.ui.tap_x_spinBox.value() tap_y = self.ui.tap_y_spinBox.value() tap_times = self.ui.tap_times_spinBox.value() tap_interval = round(self.ui.tap_interval_doubleSpinBox.value(), 1) tap_random_interval = self.ui.tap_random_interval_checkBox.isChecked( ) # 模拟滑屏 swipe_x1_min = self.ui.swipe_x1_min_spinBox.value() swipe_x1_max = self.ui.swipe_x1_max_spinBox.value() swipe_y1_min = self.ui.swipe_y1_min_spinBox.value() swipe_y1_max = self.ui.swipe_y1_max_spinBox.value() swipe_x2_min = self.ui.swipe_x2_min_spinBox.value() swipe_x2_max = self.ui.swipe_x2_max_spinBox.value() swipe_y2_min = self.ui.swipe_y2_min_spinBox.value() swipe_y2_max = self.ui.swipe_y2_max_spinBox.value() swipe_times = self.ui.swipe_times_spinBox.value() # 浮点数取整 swipe_interval = round( self.ui.swipe_interval_doubleSpinBox.value(), 1) swipe_random_interval = self.ui.swipe_random_interval_checkBox.isChecked( ) swipe_60 = self.ui.swipe_60_checkBox.isChecked() # 组成字典 params = { 'ip': ip, 'port': port, 'tap_x': tap_x, 'tap_y': tap_y, 'tap_times': tap_times, 'tap_interval': tap_interval, 'tap_random_interval': tap_random_interval, 'swipe_x1_min': swipe_x1_min, 'swipe_x1_max': swipe_x1_max, 'swipe_y1_min': swipe_y1_min, 'swipe_y1_max': swipe_y1_max, 'swipe_x2_min': swipe_x2_min, 'swipe_x2_max': swipe_x2_max, 'swipe_y2_min': swipe_y2_min, 'swipe_y2_max': swipe_y2_max, 'swipe_times': swipe_times, 'swipe_interval': swipe_interval, 'swipe_random_interval': swipe_random_interval, 'swipe_60': swipe_60 } # 写入文件 if not filepath.endswith('.json'): filepath = filepath + '.json' with open(filepath, 'w', encoding='utf-8') as f: json.dump(params, f) # 输出信息 self.output_message('保存参数完成!文件路径:' + os.path.abspath(filepath)) # 加载参数 def load_params(self): # 弹出文件选择器 filepath, filetype = QFileDialog.getOpenFileName( self.ui, "请选择文件", os.getcwd(), "Json File (*.json)") # 判断 if filepath != "": # 读取文件 with open(filepath, 'r', encoding='utf-8') as f: params = json.load(f) # IP和端口 self.ui.ip_lineEdit.setText(params['ip']) self.ui.port_spinBox.setValue(params['port']) # 模拟点击 self.ui.tap_x_spinBox.setValue(params['tap_x']) self.ui.tap_y_spinBox.setValue(params['tap_y']) self.ui.tap_times_spinBox.setValue(params['tap_times']) self.ui.tap_interval_doubleSpinBox.setValue( params['tap_interval']) self.ui.tap_random_interval_checkBox.setChecked( params['tap_random_interval']) # 模拟滑屏 self.ui.swipe_x1_max_spinBox.setValue(params['swipe_x1_max']) self.ui.swipe_x1_min_spinBox.setValue(params['swipe_x1_min']) self.ui.swipe_y1_max_spinBox.setValue(params['swipe_y1_max']) self.ui.swipe_y1_min_spinBox.setValue(params['swipe_y1_min']) self.ui.swipe_x2_max_spinBox.setValue(params['swipe_x2_max']) self.ui.swipe_x2_min_spinBox.setValue(params['swipe_x2_min']) self.ui.swipe_y2_max_spinBox.setValue(params['swipe_y2_max']) self.ui.swipe_y2_min_spinBox.setValue(params['swipe_y2_min']) self.ui.swipe_times_spinBox.setValue(params['swipe_times']) self.ui.swipe_interval_doubleSpinBox.setValue( params['swipe_interval']) self.ui.swipe_random_interval_checkBox.setChecked( params['swipe_random_interval']) self.ui.swipe_60_checkBox.setChecked(params['swipe_60']) # 输出信息 self.output_message('加载参数完成!文件路径:' + os.path.abspath(filepath)) # 退出 def exit(self): # 保存日志 # 断开连接 self.disconnect() # 退出 self.ui.close() # 断开连接 def disconnect(self): # 停止 self.stop() # 断开连接 result, error = ADBTool().disconnect() # 输出信息 self.output_result_error(result, error) self.connected = False self.output_message('已经断开连接') # 按钮可点 self.ui.tap_pushButton.setEnabled(True) self.ui.swipe_pushButton.setEnabled(True) # 清空输出信息 def clear(self): self.ui.output_textEdit.setText('') # 关于 def about(self): # 显示弹窗 QMessageBox.about( self.ui, '关于', 'ADB助手\n© Copyright 2020\n作者:ordinary-student\n版本:v1.0.0') # 打开ADB def open_adb(self): # 获取IP地址 ip = self.ui.ip_lineEdit.text() # IP校验 if len(ip.strip()) == 0: self.ui.ip_lineEdit.setText('') # 显示弹窗 QMessageBox.information(self.ui, '提示', '请填写IP地址!') return # 获取端口号 port = self.ui.port_spinBox.value() # 创建ADB工具 adbtool = ADBTool(ip, port) # 启动ADB result, error = adbtool.open() # 输出信息 self.output_result_error(result, error) # 判断是否已经启动 if ('restarting' in result) and ('error' not in error): self.adbtool = adbtool self.output_message('ADB已经启动') # 连接设备 def connect(self): # 判断 if self.adbtool == None: # 显示弹窗 QMessageBox.information(self.ui, '提示', 'ADB尚未启动!') return # 连接 try: result, error = self.adbtool.connect() # 输出信息 self.output_result_error(result, error) # 判断是否已经启动 if ('connected' in result) and ('error' not in error): self.connected = True self.output_message('已经连接设备') self.adbtool.tap(700, 1860) except: self.output_message('设备连接失败') # 显示弹窗 QMessageBox.information( self.ui, '提示', '设备连接失败!\n请检查设备和电脑是否处于同一局域网,\n检查设备的USB调试模式是否已经打开。\n若还是不行,请重启软件再尝试。' ) return # 显示设备列表 def show_devices(self): # 显示设备列表 result, error = ADBTool().show_devices() # 输出信息 self.output_result_error(result, error) # 开始点击 def tap(self): # 判断ADB是否启动 if self.adbtool == None: # 显示弹窗 QMessageBox.information(self.ui, '提示', 'ADB尚未启动!') return # 判断是否连接 if self.connected: tap_thread = Thread(target=self.tap2) tap_thread.start() else: # 显示弹窗 QMessageBox.information(self.ui, '提示', '尚未连接设备!') return # 开始点击 def tap2(self): # 按钮不可点 self.ui.tap_pushButton.setEnabled(False) # 获取参数 tap_x = self.ui.tap_x_spinBox.value() tap_y = self.ui.tap_y_spinBox.value() tap_times = self.ui.tap_times_spinBox.value() tap_interval = round(self.ui.tap_interval_doubleSpinBox.value(), 1) tap_random_interval = self.ui.tap_random_interval_checkBox.isChecked() if tap_random_interval: message = '点击坐标({},{})处,{}次,时间间隔随机'.format(tap_x, tap_y, tap_times) else: message = '点击坐标({},{})处,{}次,时间间隔{}秒'.format( tap_x, tap_y, tap_times, tap_interval) self.output_message(message) # 模拟点击 if self.adbtool.continuous_tap(tap_x, tap_y, tap_times, tap_interval, tap_random_interval): self.output_message('模拟点击已完成') else: self.output_message('模拟点击已停止') # 按钮可点 self.ui.tap_pushButton.setEnabled(True) # 开始滑屏 def swipe(self): # 判断ADB是否启动 if self.adbtool == None: # 显示弹窗 QMessageBox.information(self.ui, '提示', 'ADB尚未启动!') return # 判断是否连接 if self.connected: swipe_thread = Thread(target=self.swipe2) swipe_thread.start() else: # 显示弹窗 QMessageBox.information(self.ui, '提示', '尚未连接设备!') return # 开始滑屏 def swipe2(self): # 按钮不可点 self.ui.swipe_pushButton.setEnabled(False) # 获取参数 swipe_x1_min = self.ui.swipe_x1_min_spinBox.value() swipe_x1_max = self.ui.swipe_x1_max_spinBox.value() swipe_y1_min = self.ui.swipe_y1_min_spinBox.value() swipe_y1_max = self.ui.swipe_y1_max_spinBox.value() swipe_x2_min = self.ui.swipe_x2_min_spinBox.value() swipe_x2_max = self.ui.swipe_x2_max_spinBox.value() swipe_y2_min = self.ui.swipe_y2_min_spinBox.value() swipe_y2_max = self.ui.swipe_y2_max_spinBox.value() swipe_times = self.ui.swipe_times_spinBox.value() swipe_interval = round(self.ui.swipe_interval_doubleSpinBox.value(), 1) swipe_random_interval = self.ui.swipe_random_interval_checkBox.isChecked( ) swipe_60 = self.ui.swipe_60_checkBox.isChecked() # 定时60秒 if swipe_60: message = '从坐标({}~{},{}~{})滑到({}~{},{}~{})处,连续滑屏60秒,时间间隔{}秒'.format( swipe_x1_min, swipe_x1_max, swipe_y1_min, swipe_y1_max, swipe_x2_min, swipe_x2_max, swipe_y2_min, swipe_y2_max, swipe_interval) self.output_message(message) # 模拟连续滑屏60秒 if self.adbtool.timing_swipe( (swipe_x1_min, swipe_x1_max), (swipe_y1_min, swipe_y1_max), (swipe_x2_min, swipe_x2_max), (swipe_y2_min, swipe_y2_max), swipe_interval, swipe_random_interval): self.output_message('模拟滑屏已完成') else: self.output_message('模拟滑屏已停止') else: if swipe_random_interval: message = '从坐标({}~{},{}~{})滑到({}~{},{}~{})处,{}次,时间间隔随机'.format( swipe_x1_min, swipe_x1_max, swipe_y1_min, swipe_y1_max, swipe_x2_min, swipe_x2_max, swipe_y2_min, swipe_y2_max, swipe_times) else: message = '从坐标({}~{},{}~{})滑到({}~{},{}~{})处,{}次,时间间隔{}秒'.format( swipe_x1_min, swipe_x1_max, swipe_y1_min, swipe_y1_max, swipe_x2_min, swipe_x2_max, swipe_y2_min, swipe_y2_max, swipe_times, swipe_interval) self.output_message(message) # 模拟滑屏 if self.adbtool.random_swipe( (swipe_x1_min, swipe_x1_max), (swipe_y1_min, swipe_y1_max), (swipe_x2_min, swipe_x2_max), (swipe_y2_min, swipe_y2_max), swipe_times, swipe_interval, swipe_random_interval): self.output_message('模拟滑屏已完成') else: self.output_message('模拟滑屏已停止') # 按钮可点 self.ui.swipe_pushButton.setEnabled(True) # 停止 def stop(self): if self.adbtool != None: self.adbtool.stop() # 按钮可点 self.ui.tap_pushButton.setEnabled(True) self.ui.swipe_pushButton.setEnabled(True) # 截图 def screen_cap(self): if self.adbtool != None: # 截图 photo_path = self.adbtool.screen_cap() # 获取图片到本地 result, error = self.adbtool.pull_file(photo_path) self.output_result_error(result, error) # 判断 if ('png' in result) and ('error' not in error): path = photo_path[(photo_path.rindex('/') + 1):] self.output_message('截图成功!图片路径:' + os.path.abspath(path)) return os.path.abspath(path) else: self.output_message('截图失败!') return None else: return None # 坐标工具 def tool(self): # 判断ADB是否启动 if self.adbtool == None: # 显示弹窗 QMessageBox.information(self.ui, '提示', 'ADB尚未启动!') return # 判断是否连接 if self.connected: self.axis_tool() else: # 显示弹窗 QMessageBox.information(self.ui, '提示', '尚未连接设备!') return # 坐标工具 def axis_tool(self): w = 300 h = 600 # 判断 if self.tool_dialog == None: # 创建坐标工具窗 self.tool_dialog = QDialog(self.ui) self.tool_dialog.setWindowTitle('坐标工具') self.tool_dialog.resize(w, h) # 截图 photo_path = self.screen_cap() if photo_path != None: if self.screen_cap_file != None: os.remove(self.screen_cap_file) self.screen_cap_file = photo_path pix = QPixmap(photo_path) w = pix.width() h = pix.height() # 设置面板大小 self.tool_dialog.setFixedSize(w / 4, h / 4) # 调色板 palette = QPalette() # 缩小图片 pix = pix.scaled(w / 4, h / 4) palette.setBrush(self.tool_dialog.backgroundRole(), QBrush(pix)) self.tool_dialog.setAutoFillBackground(True) self.tool_dialog.setPalette(palette) self.tool_dialog.setMouseTracking(True) # 绑定鼠标移动事件 self.tool_dialog.mouseMoveEvent = self.mouse_move # 显示窗口 self.tool_dialog.show() # 十字光标 self.tool_dialog.setCursor(Qt.CrossCursor) # 鼠标移动 def mouse_move(self, event): x = event.pos().x() y = event.pos().y() #print(x, y) self.tool_dialog.setWindowTitle('X:{},Y:{}'.format(x * 4, y * 4)) # 限制数值范围 def x1_min(self): if self.ui.swipe_x1_min_spinBox.value( ) >= self.ui.swipe_x1_max_spinBox.value(): self.ui.swipe_x1_min_spinBox.setValue( self.ui.swipe_x1_max_spinBox.value()) # def x1_max(self): if self.ui.swipe_x1_max_spinBox.value( ) <= self.ui.swipe_x1_min_spinBox.value(): self.ui.swipe_x1_max_spinBox.setValue( self.ui.swipe_x1_min_spinBox.value()) # def y1_min(self): if self.ui.swipe_y1_min_spinBox.value( ) >= self.ui.swipe_y1_max_spinBox.value(): self.ui.swipe_y1_min_spinBox.setValue( self.ui.swipe_y1_max_spinBox.value()) # def y1_max(self): if self.ui.swipe_y1_max_spinBox.value( ) <= self.ui.swipe_y1_min_spinBox.value(): self.ui.swipe_y1_max_spinBox.setValue( self.ui.swipe_y1_min_spinBox.value()) # def x2_min(self): if self.ui.swipe_x2_min_spinBox.value( ) >= self.ui.swipe_x2_max_spinBox.value(): self.ui.swipe_x2_min_spinBox.setValue( self.ui.swipe_x2_max_spinBox.value()) # def x2_max(self): if self.ui.swipe_x2_max_spinBox.value( ) <= self.ui.swipe_x2_min_spinBox.value(): self.ui.swipe_x2_max_spinBox.setValue( self.ui.swipe_x2_min_spinBox.value()) # def y2_min(self): if self.ui.swipe_y2_min_spinBox.value( ) >= self.ui.swipe_y2_max_spinBox.value(): self.ui.swipe_y2_min_spinBox.setValue( self.ui.swipe_y2_max_spinBox.value()) # def y2_max(self): if self.ui.swipe_y2_max_spinBox.value( ) <= self.ui.swipe_y2_min_spinBox.value(): self.ui.swipe_y2_max_spinBox.setValue( self.ui.swipe_y2_min_spinBox.value())
class SmartSyncDialog(object): def __init__(self, parent): self._dialog = QDialog(parent) self._dialog.setWindowIcon(QIcon(':/images/icon.png')) self._ui = Ui_Dialog() self._ui.setupUi(self._dialog) self._ui.centralWidget.setFrameShape(QFrame.NoFrame) self._ui.centralWidget.setLineWidth(1) self._model = None self._proxy_model = QSortFilterProxyModel() self._view = self._ui.folder_list_view self._view.setModel(self._proxy_model) self._view.expanded.connect(self.on_item_expanded) self._offline_paths = None # for frameless window moving self._x_coord = 0 self._y_coord = 0 self._dialog.mousePressEvent = self.on_mouse_press_event self._dialog.mouseMoveEvent = self.on_mouse_move_event self._loader_movie = QMovie(":/images/loader.gif") self._ui.loader_label.setMovie(self._loader_movie) def on_mouse_press_event(self, ev): self._x_coord = ev.x() self._y_coord = ev.y() def on_mouse_move_event(self, ev): self._dialog.move( ev.globalX() - self._x_coord, ev.globalY() - self._y_coord) def on_item_expanded(self, index): if self._model: self._model.on_item_expanded(self._proxy_model.mapToSource(index)) def show(self, root_path, hide_dotted=False): if LOGGING_ENABLED: logger.info( "Opening smart sync dialog for path '%s'...", root_path) self._model = TreeModel( root_path, hide_dotted=hide_dotted) self._proxy_model.setSourceModel(self._model) self.show_cursor_loading(show_movie=True) # Execute dialog result = self._dialog.exec_() if result == QDialog.Accepted: offline_dirs = self._model.get_added_to_offline_paths() new_online = list(self._model.get_removed_from_offline_paths()) new_offline = list(offline_dirs - self._offline_paths) if LOGGING_ENABLED: logger.debug("new offline dirs %s, new online dirs %s", new_offline, new_online) return new_offline, new_online else: return [], [] def set_offline_paths(self, offline_paths): self._offline_paths = offline_paths logger.debug("offline paths %s", offline_paths) self._model.set_offline_dirs(offline_paths) self.show_cursor_normal() self._view.expand(self._proxy_model.mapFromSource( self._model.get_root_path_index())) self._proxy_model.sort(0, Qt.AscendingOrder) def show_cursor_loading(self, show_movie=False): if show_movie: self._ui.stackedWidget.setCurrentIndex(1) self._loader_movie.start() else: self._dialog.setCursor(Qt.WaitCursor) def show_cursor_normal(self): self._dialog.setCursor(Qt.ArrowCursor) if self._loader_movie.state() == QMovie.Running: self._loader_movie.stop() self._ui.stackedWidget.setCurrentIndex(0)