def __exit__(self, *exc): ret = super().__exit__(*exc) # build table here layout = QGridLayout() for y, row in enumerate(self.rows): x = 0 for col in row.cols: layout.addLayout(col.layout, y, x, 1, col.colspan) x += col.colspan qDlgStackTop().addChild(layout) return ret
def __init__(self, parent=None): super().__init__(parent) self.lineEditPPScannos = QLineEdit() self.lineEditPPScannos.setReadOnly(True) self.comboScannoFiles = QComboBox() labelPPScannosLoc = QLabel('PPScannos File') labelPPScannosLoc.setBuddy(self.lineEditPPScannos) labelScannoLoc = QLabel('Default Scanno File') labelScannoLoc.setBuddy(self.comboScannoFiles) self.buttonPPScannos = QPushButton('Change') self.buttonPPScannos.pressed.connect(self.openFileDlg) hbox = QHBoxLayout() hbox.addWidget(labelPPScannosLoc) hbox.addWidget(self.lineEditPPScannos) hbox.addWidget(self.buttonPPScannos) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) mainLayout = QGridLayout() mainLayout.addLayout(hbox, 0, 0, 2, 0) mainLayout.addWidget(labelScannoLoc, 1, 0) mainLayout.addWidget(self.comboScannoFiles, 1, 1) mainLayout.addWidget(self.buttonBox, 5, 0, 1, 2) self.setLayout(mainLayout) self.populate() self.lineEditPPScannos.textChanged.connect(self.ppscannosChanged) self.setWindowTitle("Configure Gui Scannos") self.resize(650, 400)
class Config(QDialog): ''' Configuration dialog for single book conversion. If accepted, has the following important attributes output_format - Output format (without a leading .) input_format - Input format (without a leading .) opf_path - Path to OPF file with user specified metadata cover_path - Path to user specified cover (can be None) recommendations - A pickled list of 3 tuples in the same format as the recommendations member of the Input/Output plugins. ''' def __init__(self, parent, db, book_id, preferred_input_format=None, preferred_output_format=None): QDialog.__init__(self, parent) self.setupUi() self.opt_individual_saved_settings.setVisible(False) self.db, self.book_id = db, book_id self.setup_input_output_formats(self.db, self.book_id, preferred_input_format, preferred_output_format) self.setup_pipeline() self.input_formats.currentIndexChanged[native_string_type].connect( self.setup_pipeline) self.output_formats.currentIndexChanged[native_string_type].connect( self.setup_pipeline) self.groups.setSpacing(5) self.groups.activated[(QModelIndex)].connect(self.show_pane) self.groups.clicked[(QModelIndex)].connect(self.show_pane) self.groups.entered[(QModelIndex)].connect(self.show_group_help) rb = self.buttonBox.button(self.buttonBox.RestoreDefaults) rb.setText(_('Restore &defaults')) rb.clicked.connect(self.restore_defaults) self.groups.setMouseTracking(True) geom = gprefs.get('convert_single_dialog_geom', None) if geom: self.restoreGeometry(geom) else: self.resize(self.sizeHint()) def setupUi(self): self.setObjectName("Dialog") self.resize(1024, 700) self.setWindowIcon(QIcon(I('convert.png'))) self.gridLayout = QGridLayout(self) self.gridLayout.setObjectName("gridLayout") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.input_label = QLabel(self) self.input_label.setObjectName("input_label") self.horizontalLayout.addWidget(self.input_label) self.input_formats = QComboBox(self) self.input_formats.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.input_formats.setMinimumContentsLength(5) self.input_formats.setObjectName("input_formats") self.horizontalLayout.addWidget(self.input_formats) self.opt_individual_saved_settings = QCheckBox(self) self.opt_individual_saved_settings.setObjectName( "opt_individual_saved_settings") self.horizontalLayout.addWidget(self.opt_individual_saved_settings) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.label_2 = QLabel(self) self.label_2.setObjectName("label_2") self.horizontalLayout.addWidget(self.label_2) self.output_formats = QComboBox(self) self.output_formats.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.output_formats.setMinimumContentsLength(5) self.output_formats.setObjectName("output_formats") self.horizontalLayout.addWidget(self.output_formats) self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 2) self.groups = QListView(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.groups.sizePolicy().hasHeightForWidth()) self.groups.setSizePolicy(sizePolicy) self.groups.setTabKeyNavigation(True) self.groups.setIconSize(QSize(48, 48)) self.groups.setWordWrap(True) self.groups.setObjectName("groups") self.gridLayout.addWidget(self.groups, 1, 0, 3, 1) self.scrollArea = QScrollArea(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(4) sizePolicy.setVerticalStretch(10) sizePolicy.setHeightForWidth( self.scrollArea.sizePolicy().hasHeightForWidth()) self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setFrameShape(QFrame.NoFrame) self.scrollArea.setLineWidth(0) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 810, 494)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.verticalLayout_3.setObjectName("verticalLayout_3") self.stack = QStackedWidget(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.stack.sizePolicy().hasHeightForWidth()) self.stack.setSizePolicy(sizePolicy) self.stack.setObjectName("stack") self.page = QWidget() self.page.setObjectName("page") self.stack.addWidget(self.page) self.page_2 = QWidget() self.page_2.setObjectName("page_2") self.stack.addWidget(self.page_2) self.verticalLayout_3.addWidget(self.stack) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.gridLayout.addWidget(self.scrollArea, 1, 1, 1, 1) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults) self.buttonBox.setObjectName("buttonBox") self.gridLayout.addWidget(self.buttonBox, 3, 1, 1, 1) self.help = QTextEdit(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.help.sizePolicy().hasHeightForWidth()) self.help.setSizePolicy(sizePolicy) self.help.setMaximumHeight(80) self.help.setObjectName("help") self.gridLayout.addWidget(self.help, 2, 1, 1, 1) self.input_label.setBuddy(self.input_formats) self.label_2.setBuddy(self.output_formats) self.input_label.setText(_("&Input format:")) self.opt_individual_saved_settings.setText( _("Use &saved conversion settings for individual books")) self.label_2.setText(_("&Output format:")) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def sizeHint(self): desktop = QCoreApplication.instance().desktop() geom = desktop.availableGeometry(self) nh, nw = max(300, geom.height() - 100), max(400, geom.width() - 70) return QSize(nw, nh) def restore_defaults(self): delete_specifics(self.db, self.book_id) self.setup_pipeline() @property def input_format(self): return unicode_type(self.input_formats.currentText()).lower() @property def output_format(self): return unicode_type(self.output_formats.currentText()).lower() @property def manually_fine_tune_toc(self): for i in range(self.stack.count()): w = self.stack.widget(i) if hasattr(w, 'manually_fine_tune_toc'): return w.manually_fine_tune_toc.isChecked() def setup_pipeline(self, *args): oidx = self.groups.currentIndex().row() input_format = self.input_format output_format = self.output_format self.plumber = create_dummy_plumber(input_format, output_format) def widget_factory(cls): return cls(self.stack, self.plumber.get_option_by_name, self.plumber.get_option_help, self.db, self.book_id) self.mw = widget_factory(MetadataWidget) self.setWindowTitle( _('Convert') + ' ' + unicode_type(self.mw.title.text())) lf = widget_factory(LookAndFeelWidget) hw = widget_factory(HeuristicsWidget) sr = widget_factory(SearchAndReplaceWidget) ps = widget_factory(PageSetupWidget) sd = widget_factory(StructureDetectionWidget) toc = widget_factory(TOCWidget) from calibre.gui2.actions.toc_edit import SUPPORTED toc.manually_fine_tune_toc.setVisible( output_format.upper() in SUPPORTED) debug = widget_factory(DebugWidget) output_widget = self.plumber.output_plugin.gui_configuration_widget( self.stack, self.plumber.get_option_by_name, self.plumber.get_option_help, self.db, self.book_id) input_widget = self.plumber.input_plugin.gui_configuration_widget( self.stack, self.plumber.get_option_by_name, self.plumber.get_option_help, self.db, self.book_id) while True: c = self.stack.currentWidget() if not c: break self.stack.removeWidget(c) widgets = [self.mw, lf, hw, ps, sd, toc, sr] if input_widget is not None: widgets.append(input_widget) if output_widget is not None: widgets.append(output_widget) widgets.append(debug) for w in widgets: self.stack.addWidget(w) w.set_help_signal.connect(self.help.setPlainText) self._groups_model = GroupModel(widgets) self.groups.setModel(self._groups_model) idx = oidx if -1 < oidx < self._groups_model.rowCount() else 0 self.groups.setCurrentIndex(self._groups_model.index(idx)) self.stack.setCurrentIndex(idx) try: shutil.rmtree(self.plumber.archive_input_tdir, ignore_errors=True) except: pass def setup_input_output_formats(self, db, book_id, preferred_input_format, preferred_output_format): if preferred_output_format: preferred_output_format = preferred_output_format.upper() output_formats = get_output_formats(preferred_output_format) input_format, input_formats = get_input_format_for_book( db, book_id, preferred_input_format) preferred_output_format = preferred_output_format if \ preferred_output_format in output_formats else \ sort_formats_by_preference(output_formats, [prefs['output_format']])[0] self.input_formats.addItems( (unicode_type(x.upper()) for x in input_formats)) self.output_formats.addItems( (unicode_type(x.upper()) for x in output_formats)) self.input_formats.setCurrentIndex(input_formats.index(input_format)) self.output_formats.setCurrentIndex( output_formats.index(preferred_output_format)) def show_pane(self, index): self.stack.setCurrentIndex(index.row()) def accept(self): recs = GuiRecommendations() for w in self._groups_model.widgets: if not w.pre_commit_check(): return x = w.commit(save_defaults=False) recs.update(x) self.opf_file, self.cover_file = self.mw.opf_file, self.mw.cover_file self._recommendations = recs if self.db is not None: recs['gui_preferred_input_format'] = self.input_format save_specifics(self.db, self.book_id, recs) self.break_cycles() QDialog.accept(self) def reject(self): self.break_cycles() QDialog.reject(self) def done(self, r): if self.isVisible(): gprefs['convert_single_dialog_geom'] = \ bytearray(self.saveGeometry()) return QDialog.done(self, r) def break_cycles(self): for i in range(self.stack.count()): w = self.stack.widget(i) w.break_cycles() @property def recommendations(self): recs = [(k, v, OptionRecommendation.HIGH) for k, v in self._recommendations.items()] return recs def show_group_help(self, index): widget = self._groups_model.widgets[index.row()] self.help.setPlainText(widget.HELP)
def createWindow(self): self.status = True self.cateStatus = '' self.sizes = '' self.setWindowTitle(self.title) self.item = '' self.color = '' #Button self.button1 = QPushButton('Start Running', self) self.button1.clicked.connect( lambda: search.run(self, self.cateStatus, self.status, self.sizes, self.color, self.item)) self.button2 = QPushButton('Purchase', self) self.button2.clicked.connect(lambda: search.purchase(self)) self.button3 = QPushButton('Close', self) self.button3.clicked.connect(lambda: self.close()) self.button4 = QPushButton('Add item', self) #Dropdown menu Options = ['', 'True', 'False'] self.TF = QComboBox(self) self.TF.addItems(Options) self.TF.activated[str].connect(self.changeOption) CateOptions = [ '', 'jackets', 'shirts', 'tops/sweaters', 'sweatshirts', 'pants', 'shorts', 't-shirts', 'hats', 'bags', 'accessories' ] self.cateBox = QComboBox(self) self.cateBox.addItems(CateOptions) self.cateBox.activated[str].connect(self.changeCateOption) sizeOption = ['', 'Small', 'Medium', 'Large'] self.sizeBox = QComboBox(self) self.sizeBox.addItems(sizeOption) self.sizeBox.activated[str].connect(self.changeSize) itemList = self.item_list self.itemBox = QComboBox(self) self.itemBox.addItems(itemList) self.itemBox.activated[str].connect(self.changeitem) #Textbox self.EnterColor = QLineEdit(self) self.EnterColor.textChanged[str].connect(self.changeColor) #Label self.Name = QLabel('Name: ', self) self.Name.setFont(QtGui.QFont('Microsoft YaHei', 9)) self.Category = QLabel('Category: ', self) self.Category.setFont(QtGui.QFont('Microsoft YaHei', 9)) self.Sizes = QLabel('Size: ', self) self.Sizes.setFont(QtGui.QFont('Microsoft YaHei', 9)) self.color = QLabel('Color(True/False): ', self) self.color.setFont(QtGui.QFont('Microsoft YaHei', 9)) self.whatColor = QLabel('Color: ', self) self.whatColor.setFont(QtGui.QFont('Microsoft YaHei', 9)) #Vbox Operation = QVBoxLayout() Operation.addWidget(self.button4) Operation.addWidget(self.button1) Operation.addWidget(self.button2) Operation.addWidget(self.button3) Structure = QGridLayout() Structure.addLayout(Operation, 4, 0) Structure.addWidget(self.Name, 0, 0) Structure.addWidget(self.itemBox, 0, 1) Structure.addWidget(self.Category, 1, 0) Structure.addWidget(self.cateBox, 1, 1) Structure.addWidget(self.Sizes, 2, 0) Structure.addWidget(self.sizeBox, 2, 1) Structure.addWidget(self.color, 3, 0) Structure.addWidget(self.TF, 3, 1) Structure.addWidget(self.whatColor, 3, 2) Structure.addWidget(self.EnterColor, 3, 3) #Display self.setLayout(Structure) self.show()
class Window(QWidget): def __init__(self, cc): super().__init__() self.camCtr = cc self.initUI() def initUI(self): self.setWindowTitle('Camera Control') self.setMinimumWidth(260) self.grid = QGridLayout() self.grid.setContentsMargins(4, 4, 4, 4) self.grid.setSpacing(2) self.lbls = {} self.sls = {} self.buttons = {} self.button_status = {} row = 1 for name, c in self.camCtr.ctrls.items(): txt = name.replace("_", " ").capitalize() + ":" txt = txt.replace("White balance temperature", "WB temperature") lbl = QLabel(txt) self.grid.addWidget(lbl, row, 1, 1, 1, Qt.AlignRight) self.lbls[name] = lbl if c["type"] == "bool": button = QPushButton() if c["value"]: button.setText('ON') button.setStyleSheet("background-color: green") self.button_status[name] = True else: button.setText('OFF') button.setStyleSheet("background-color: red") self.button_status[name] = False button.clicked.connect( lambda val, name=name: self.button_Change(val, name)) self.grid.addWidget(button, row, 2, 1, 1, Qt.AlignCenter) self.buttons[name] = button else: sl = QSlider() sl.setOrientation(Qt.Horizontal) sl.setMaximum(c["max"]) sl.setMinimum(c["min"]) sl.valueChanged.connect( lambda val, name=name: self.sl_Change(val, name)) sl.setMinimumWidth(250) sl.setTickInterval(c.get("step", 1)) sl.setValue(c["value"]) if c.get("flags", "") == "inactive": lbl.setDisabled(True) sl.setDisabled(True) self.grid.addWidget(sl, row, 2, 1, 1, Qt.AlignRight) self.sls[name] = sl row += 1 self.actions_grid = QGridLayout() self.actions = {} for i, action in enumerate( ("default", "sync", "update", "load", "save")): b = QPushButton() b.setText(action.capitalize()) b.clicked.connect( lambda _, action=action: self.action_Slot(action)) self.actions_grid.addWidget(b, 1, i, 1, 1, Qt.AlignCenter) self.grid.addLayout(self.actions_grid, row, 1, 1, 2, Qt.AlignCenter) self.mainLayout = QHBoxLayout() self.mainLayout.addLayout(self.grid) self.setLayout(self.mainLayout) self.show() def sl_Change(self, val, name): if not self.camCtr.setValue(name, val): # Give user feedback if parameter was not # accepted. Unfortunately, not all invalid parameters are # actually flagged. self.sync() return def sync(self): self.camCtr.get_ctls() for name, c in self.camCtr.ctrls.items(): if c["type"] == "bool": if c["value"]: self.buttons[name].setText('ON') self.buttons[name].setStyleSheet("background-color: green") self.button_status[name] = True else: self.buttons[name].setText('OFF') self.buttons[name].setStyleSheet("background-color: red") self.button_status[name] = False else: self.sls[name].setValue(c["value"]) if c.get("flags", "") == "inactive": self.sls[name].setDisabled(True) self.lbls[name].setDisabled(True) else: self.sls[name].setDisabled(False) self.lbls[name].setDisabled(False) def button_Change(self, _, name): if self.button_status[name]: self.buttons[name].setText('OFF') self.buttons[name].setStyleSheet("background-color: red") self.button_status[name] = False self.camCtr.setValue(name, "0") else: self.buttons[name].setText('ON') self.buttons[name].setStyleSheet("background-color: green") self.button_status[name] = True self.camCtr.setValue(name, "1") # Check if any controls have become enabled. self.sync() def action_Slot(self, name): if name == "default": self.camCtr.update(reset=True) elif name == "update": self.camCtr.update() elif name == "save" or name == "load": conf_dir = os.path.join(Path.home(), ".config", "cam_control") Path(conf_dir).mkdir(parents=True, exist_ok=True) if name == "save": file_name, _ = QFileDialog.getSaveFileName( self, "Save Cam Control configuration", conf_dir, "Cam Control Conf (*.ccconf)") if file_name: if not file_name.endswith(".ccconf"): file_name += ".ccconf" with open(file_name, "w") as fd: json.dump(self.camCtr.ctrls, fd) else: file_name, _ = QFileDialog.getOpenFileName( self, "Load Cam Control configuration", conf_dir, "Cam Control Conf (*.ccconf)") if file_name: with open(file_name, "r") as fd: self.camCtr.ctrls = json.load(fd) self.camCtr.update() self.sync()
class M3Dashboard(Dashboard): """ Dashboard for Mekabot :param context: the plugin context :type context: qt_gui.plugin.Plugin """ def setup(self, context): self.name = 'Meka Dashboard' self.max_icon_size = QSize(50, 30) self._widget_initialized = False self._service_ready = True self._last_dashboard_message_time = rospy.Time.now() self._path = os.path.join(rospkg.RosPack().get_path('rqt_m3dashboard'), 'images') self._battery_icons = {} self._state_buttons = {} self._dashboard_mekaros_subs = {} self._m3field_values = {} self._m3field_plots = {} NAMESPACE = '' rospy.loginfo("Starting up...") # self._state_button = ControlStateButton("default", 9999) # TODO read this list on the parameters battery_names = ["m3pwr_pwr038", "m3pwr_pwr042"] group_names = {"left_hand":"mh26", "left_arm":"ma30", "head":"ms8", "right_arm":"ma29", "right_hand":"mh24", "zlift":"mz7", "torso":"mt6", "base":"mb7"} # create as many buttons as groups received for group_name in group_names.keys(): self._state_buttons[group_name] = ControlStateButton(group_name, 0) battery_widget = self.init_batteries(battery_names) self._dashboard_agg_sub = rospy.Subscriber("/meka_roscontrol_state_manager/state", M3ControlStates, self.state_callback, queue_size=1) self._actionclient = actionlib.SimpleActionClient("/meka_state_manager", M3StateChangeAction) rospy.loginfo("Looking for state manager...") if self._actionclient.wait_for_server(timeout=rospy.Duration(0.1)) is False: rospy.logfatal("Failed to connect to state_manager action server in 4 sec") self._service_ready = False else: rospy.loginfo("Found the state manager") self._state_control = rospy.ServiceProxy('/meka_roscontrol_state_manager/change_state', M3ControlStateChange) self._main_widget = QWidget() vlayout = QVBoxLayout() hlayout = QHBoxLayout() hlayout2 = QHBoxLayout() self.chk_all = QCheckBox("enable_all") self.chk_all.setChecked(False) self.spin_retries = QSpinBox() # infinite number of times is -1 self.spin_retries.setMinimum(-1) self.spin_retries.setMaximum(10) self.spin_retries.setValue(2) label_retries = QLabel("trial times") self.btn_start = QPushButton("start") self.btn_stop = QPushButton("stop") self.btn_freeze = QPushButton("freeze") if not self._service_ready: self.btn_start.setEnabled(False) self.btn_stop.setEnabled(False) self.btn_freeze.setEnabled(False) inspection_button = self.init_inspection() self.hz_rate = QSpinBox() # infinite number of times is -1 self.hz_rate.setMinimum(1) self.hz_rate.setMaximum(100) self.hz_rate.setValue(1) label_hz = QLabel("hz") hlayout2.addWidget(inspection_button) hlayout2.addWidget(self.hz_rate) hlayout2.addWidget(label_hz) hlayout.addWidget(self.chk_all) hlayout.addWidget(label_retries) hlayout.addWidget(self.spin_retries) self.inspection_layout = QGridLayout() self.stiffness_layout = self.init_stiffness_ctrl() #vlayout.addWidget() vlayout.addWidget(battery_widget) vlayout.addLayout(hlayout) vlayout.addWidget(self.btn_start) vlayout.addWidget(self.btn_freeze) vlayout.addWidget(self.btn_stop) vlayout.addLayout(self.stiffness_layout) vlayout.addLayout(hlayout2) vlayout.addLayout(self.inspection_layout) self.btn_start.clicked.connect(self.on_btn_start_clicked) self.btn_stop.clicked.connect(self.on_btn_stop_clicked) self.btn_freeze.clicked.connect(self.on_btn_freeze_clicked) self.chk_all.stateChanged.connect(self.on_enable_all_clicked) self._main_widget.setLayout(vlayout) self.context.add_widget(self._main_widget) # self._main_widget.addLayout(hlayout) self._widget_initialized = True def init_batteries(self, battery_names): widget = QWidget() layout = QHBoxLayout(widget) fields = ["motor_enabled", "bus_voltage"] dt = Floats for battery_name in battery_names: self._battery_icons[battery_name] = WrappedBattery(self.context, battery_name) layout.addWidget(self._battery_icons[battery_name]) self._dashboard_mekaros_subs[(battery_name, fields[0])] = rospy.Subscriber("/meka_ros_pub/"+battery_name+"/"+fields[0], dt, self.battery_pwrd_cb, battery_name) self._dashboard_mekaros_subs[(battery_name, fields[1])] = rospy.Subscriber("/meka_ros_pub/"+battery_name+"/"+fields[1], dt, self.battery_voltage_cb, battery_name) layout.addStretch(1) widget.setFixedHeight(75) #self.bat_lbb = QLabel("Battery voltage") #self.bat_txt = QLabel() #self.bat_txt.setText("0.0") return widget def init_stiffness_ctrl(self): slayout = QVBoxLayout() prefix = "meka_roscontrol" suffix = "stiffness_controller/command" button = QPushButton("Stiffness controller (beta)") self.stiffness_pub = rospy.Publisher("/" + prefix + "/" + suffix, Float64MultiArray, queue_size=1) group_names = ["right_arm", "left_arm", "right_hand", "left_hand", "head", "torso", "zlift"] # slider for each group joint_names = [ "right_arm_j0", "right_arm_j1", "right_arm_j2", "right_arm_j3", "right_arm_j4", "right_arm_j5", "right_arm_j6", "left_arm_j0", "left_arm_j1", "left_arm_j2", "left_arm_j3", "left_arm_j4", "left_arm_j5", "left_arm_j6", "right_hand_j0", "right_hand_j1", "right_hand_j2", "right_hand_j3", "right_hand_j4", "left_hand_j0", "left_hand_j1", "left_hand_j2", "left_hand_j3", "left_hand_j4", "head_j0", "head_j1", "torso_j0", "torso_j1", "zlift_j0"] self._stiffness_dict = OrderedDict((name, 1.0) for name in joint_names) menu = QMenu("Menu") menu.setStyleSheet("QMenu { menu-scrollable: 1; }"); self.stiffnessvals = {} for group in group_names: glayout = QHBoxLayout() glayout.addWidget(QLabel(group)) slider = QSlider(Qt.Horizontal) slider.setRange(0,100) slider.setValue(100) slider.setTickPosition(QSlider.TicksBelow) slider.setTickInterval(10) slider.setFixedSize(200,15) slider.setSingleStep(10) slider.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) val = QLabel("1.0") btn = QPushButton("apply") self.stiffnessvals[group] = val btn.clicked.connect(partial(self.on_stiffness_apply, group)) glayout.addWidget(slider) glayout.addWidget(val) glayout.addWidget(btn) slider.valueChanged.connect(partial(self.on_stiffness_change, slider, val, group)) slayout.addLayout(glayout) groupm = menu.addMenu(group) #for joint in joint_names: #groupm.addAction("set stiffness", partial(self.set_stiffness, groupm)) #if group in joint: # groupm.addAction(self._stiffness_dict[joint]) # s.addAction(joint, partial(self.request_fields, component, s)) button.setMenu(menu) return slayout def init_inspection(self): button = QPushButton("Robot inspection (beta)") service_list_comps = '/meka_ros_publisher/list_components' service_list_fields = '/meka_ros_publisher/list_fields' service_req_values = '/meka_ros_publisher/request_values' rospy.loginfo("Waiting for %s, %s and %s", service_list_comps, service_list_fields, service_req_values) try: rospy.wait_for_service(service_list_comps, 4.0) rospy.wait_for_service(service_list_fields, 4.0) rospy.wait_for_service(service_req_values, 4.0) except rospy.ROSException: rospy.logerr("%s and/or %s did not show up. Giving up", service_list_comps, service_list_fields) return button self.list_comps_client = rospy.ServiceProxy(service_list_comps, ListComponents) self.list_fields_client = rospy.ServiceProxy(service_list_fields, ListFields) self.req_vals_client = rospy.ServiceProxy(service_req_values, RequestValues) rospy.loginfo("Found %s, %s and %s", service_list_comps, service_list_fields, service_req_values) # get all the components try: resp = self.list_comps_client("") except rospy.ServiceException: rospy.logerr("Could not call list_components") return button menu = QMenu("Menu") menu.setStyleSheet("QMenu { menu-scrollable: 1; }"); submenus = [] self.req_action = {} if(resp): for component in resp.components: s = menu.addMenu(component) self.req_action[component] = s.addAction("request fields", partial(self.request_fields, component, s)) button.setMenu(menu) return button def init_inspection_test(self): button = QPushButton("Robot inspection (beta)") menu = QMenu("Menu") menu.setStyleSheet("QMenu { menu-scrollable: 1; }"); submenus = [] for i in range(5): # a component has fields which are either strings or arrays. s = menu.addMenu(str(i)) for j in range(5): s.addAction(str(j), partial(self.subscribe_to_field_test, "blubber", j)) button.setMenu(menu) return button def testbaloon(self, name): name_label = QLabel(name) lineedit = QLineEdit("random") name_label.setBuddy(lineedit); close_btn = QPushButton() pixmap = QPixmap(self._path + "/close.png") icon = QIcon(pixmap); close_btn.setIcon(icon) close_btn.setIconSize(pixmap.rect().size()) idx = self.inspection_layout.rowCount() close_btn.clicked.connect(partial(self.remove_row, self.inspection_layout, idx, False)) self.inspection_layout.addWidget(name_label, idx, 0); self.inspection_layout.addWidget(lineedit, idx, 1); self.inspection_layout.addWidget(close_btn, idx, 2); def subscribe_to_field_test(self, component, bla): field = str(bla) if (component, field) in self._m3field_values: rospy.logwarn("Already subscribed to field. Exiting.") return dt = Floats topic = str("/meka_ros_pub/" + component + "/" + field) self._dashboard_mekaros_subs[(component, field)] = rospy.Subscriber(topic, dt, self.field_callback, (component, field)) self._m3field_values[(component, field)] = [] name_label = QLabel(component + "->" + field + ":") for val in range(bla): label = QLabel(str(val)[:5]) label.setStyleSheet("border: 2px solid grey"); self._m3field_values[(component, field)].append(label) idx = self.inspection_layout.rowCount() plot_pixmap = QPixmap(self._path + "/plot.png") plot_icon = QIcon(plot_pixmap); plot_btn = QPushButton() plot_btn.setIcon(plot_icon) plot_btn.setIconSize(plot_pixmap.rect().size()) plot_btn.setFixedWidth(30) plot_btn.clicked.connect(partial(self.plot_values, component, field)) close_pixmap = QPixmap(self._path + "/close.png") close_icon = QIcon(close_pixmap); close_btn = QPushButton() close_btn.setIcon(close_icon) close_btn.setIconSize(close_pixmap.rect().size()) close_btn.setFixedWidth(30) close_btn.clicked.connect(partial(self.remove_row, self.inspection_layout, idx, False, component, field)) self.inspection_layout.addWidget(name_label, idx, 0) val_layout = QHBoxLayout() for label in self._m3field_values[(component, field)]: print label val_layout.addWidget(label); self.inspection_layout.addLayout(val_layout, idx, 1) self.inspection_layout.addWidget(plot_btn, idx, 2) self.inspection_layout.addWidget(close_btn, idx, 3) def request_fields(self, component, top_menu): # a component has fields which are either strings or arrays. try: resp2 = self.list_fields_client(component) except rospy.ServiceException: rospy.logerr("Could not call list_fields") return if(resp2): for field in resp2.fields: top_menu.addAction(field, partial(self.subscribe_to_field, component, field)) self.req_action[component].setEnabled(False) def subscribe_to_field(self, component, field): if (component, field) in self._m3field_values: rospy.logwarn("Already subscribed to field. Exiting.") return try: resp = self.req_vals_client(component, field, "", self.hz_rate.value()) except rospy.ServiceException: rospy.logerr("Could not call request_values") return print resp.values dt = Floats topic = str("/meka_ros_pub/"+component+"/"+field) self._dashboard_mekaros_subs[(component, field)] = rospy.Subscriber(topic, dt, self.field_callback, (component, field)) self._m3field_values[(component, field)] = [] name_label = QLabel(component+"->"+field+":") for val in resp.values: label = QLabel(str(val)[:5]) label.setStyleSheet("border: 2px solid grey"); self._m3field_values[(component, field)].append(label) idx = self.inspection_layout.rowCount() plot_pixmap = QPixmap(self._path + "/plot.png") plot_icon = QIcon(plot_pixmap); #plot_btn = QPushButton() #plot_btn.setIcon(plot_icon) #plot_btn.setIconSize(plot_pixmap.rect().size()) #plot_btn.setFixedWidth(30) #plot_btn.clicked.connect(partial(self.plot_values, component, field)) close_pixmap = QPixmap(self._path + "/close.png") close_icon = QIcon(close_pixmap); close_btn = QPushButton() close_btn.setIcon(close_icon) close_btn.setIconSize(close_pixmap.rect().size()) close_btn.setFixedWidth(30) close_btn.clicked.connect(partial(self.remove_row, self.inspection_layout, idx, False, component, field)) self.inspection_layout.addWidget(name_label, idx, 0) val_layout = QHBoxLayout() for label in self._m3field_values[(component, field)]: val_layout.addWidget(label); self.inspection_layout.addLayout(val_layout, idx, 1) #self.inspection_layout.addWidget(plot_btn, idx, 2) self.inspection_layout.addWidget(close_btn, idx, 3) def plot_values(self, component, field): """ plot_values create a new plot for the values of the given component and field :params component, field: :type component: Identifier of the component, field: Identifier of the field """ dialog = PlotDialog() QObject.connect(dialog, SIGNAL('rejected()'), partial(self.on_plot_close, component, field)) dialog.init_plot(component, field) dialog.show() self._m3field_plots[(component, field)] = dialog #dialog.exec_() def change_state(self, cmd): """ change_state calls the m3rosctrl robot interface to change the state of one or multiple joint groups (e.g. "head" to "freeze") :params cmd: :type cmd: Identifier of the new state """ goal = M3StateChangeGoal() goal.retries = 0 if self.spin_retries.value() == -1: goal.strategy = M3StateChangeGoal.KEEP_TRYING if self.spin_retries.value() == 0: goal.strategy = M3StateChangeGoal.HALT_ON_FAILURE if self.spin_retries.value() == 1: goal.strategy = M3StateChangeGoal.BEST_POSSIBLE if self.spin_retries.value() > 1: goal.strategy = M3StateChangeGoal.RETRY_N_TIMES goal.retries = self.spin_retries.value() # find enabled groups for group_name in self._state_buttons: if self._state_buttons[group_name]._enable_menu.isChecked(): goal.command.group_name.append(group_name) goal.command.state.append(cmd) try: if len(goal.command.group_name) > 0: self._actionclient.send_goal(goal) except rospy.ROSException: rospy.logerr("Failed to call change state") def on_stiffness_apply(self, group): print "change stiffness" msg = Float64MultiArray() for name in self._stiffness_dict: msg.data.append(self._stiffness_dict[name]) rospy.logdebug(msg) self.stiffness_pub.publish(msg) def on_stiffness_change(self, slider, val, group): newval = float(slider.value())/100.0 for key, value in self._stiffness_dict.iteritems(): if group in key: self._stiffness_dict[key] = newval val.setText(str(newval)) def on_enable_all_clicked(self): """ enable all """ state_cmd = M3ControlStateChangeRequest() for group_name in self._state_buttons: state_cmd.command.group_name.append(group_name) if self.chk_all.isChecked(): self._state_buttons[group_name]._enable_menu.setChecked(True) self._state_buttons[group_name]._disable_menu.setChecked(False) self._state_buttons[group_name]._enable_menu.setEnabled(False) self._state_buttons[group_name]._disable_menu.setEnabled(True) state_cmd.command.state.append(STATE_CMD_ENABLE) else: self._state_buttons[group_name]._enable_menu.setChecked(False) self._state_buttons[group_name]._disable_menu.setChecked(True) self._state_buttons[group_name]._enable_menu.setEnabled(True) self._state_buttons[group_name]._disable_menu.setEnabled(False) state_cmd.command.state.append(STATE_CMD_DISABLE) try: self._state_control(state_cmd) except rospy.ServiceException, e: QMessageBox.critical(self, "Error", "Service call failed with error: %s" % (e), "Error")
class _ExecuteTab(QTabWidget): """Tab used to execute modules or shell commands on the selected bot.""" def __init__(self, responses_tab: _ResponsesTab, model): super().__init__() self._model = model self._current_layout = None self._current_bot = None self._layout = QGridLayout() self._sub_layout = QVBoxLayout() self._module_view = ModuleView(responses_tab) self._layout.setAlignment(Qt.AlignTop) self.setLayout(self._layout) self.set_empty_layout() def set_current_bot(self, bot: Bot): """Sets the connected bot this tab will interact with.""" self._current_bot = bot def _clear_layout(self): while self._layout.count(): child = self._layout.takeAt(0) if child.widget(): child.widget().deleteLater() while self._sub_layout.count(): child = self._sub_layout.takeAt(0) if child.widget(): child.widget().deleteLater() def set_empty_layout(self): """Default layout shown when the user has not yet selected a row.""" self._current_layout = "Empty" self._clear_layout() self._layout.addWidget( QLabel("Please select a bot in the table above."), 0, 0) def set_module_layout(self, module_name: str = "screenshot"): """Sets the layout which can execute modules.""" self._current_layout = "Module" self._clear_layout() command_type_label = QLabel("Command type: ") command_type_combobox = QComboBox() command_type_combobox.addItem("Module") command_type_combobox.addItem("Shell") module_label = QLabel("Module name: ") module_combobox = QComboBox() for module_name in modules.get_names(): module_combobox.addItem(module_name) module_combobox.currentTextChanged.connect(self._on_module_change) command_type_combobox.currentTextChanged.connect( self._on_command_type_change) self._layout.setColumnStretch(1, 1) self._layout.addWidget(command_type_label, 0, 0) self._layout.addWidget(command_type_combobox, 0, 1) self._layout.addWidget(module_label, 1, 0) self._layout.addWidget(module_combobox, 1, 1) # Module layout cached_module = modules.get_module(module_name) if not cached_module: cached_module = modules.load_module(module_name, self._module_view, self._model) input_fields = [] for option_name in cached_module.get_setup_messages(): input_field = QLineEdit() self._sub_layout.addWidget(QLabel(option_name)) self._sub_layout.addWidget(input_field) input_fields.append(input_field) run_button = QPushButton("Run") run_button.setMaximumWidth(250) run_button.setMinimumHeight(25) run_button.pressed.connect(lambda: self._on_module_run( module_combobox.currentText(), input_fields)) self._sub_layout.addWidget(QLabel("")) self._sub_layout.addWidget(run_button) self._sub_layout.setContentsMargins(0, 15, 0, 0) self._layout.addLayout(self._sub_layout, self._layout.rowCount() + 2, 0, 1, 2) self._on_module_change(module_combobox.currentText()) def set_shell_layout(self): """Sets the layout which can execute shell commands.""" self._current_layout = "Shell" self._clear_layout() command_type_label = QLabel("Command type: ") command_type_combobox = QComboBox() command_type_combobox.addItem("Shell") command_type_combobox.addItem("Module") command_label = QLabel("Command:") command_input = QLineEdit() run_button = QPushButton("Run") run_button.setMaximumWidth(250) run_button.setMinimumHeight(25) command_type_combobox.currentTextChanged.connect( self._on_command_type_change) run_button.pressed.connect(lambda: self._on_command_run(command_input)) self._layout.addWidget(command_type_label, 0, 0) self._layout.addWidget(command_type_combobox, 0, 1) self._layout.addWidget(command_label, 1, 0) self._layout.addWidget(command_input, 1, 1) self._sub_layout.addWidget(QLabel("")) self._sub_layout.addWidget(run_button) self._sub_layout.setContentsMargins(0, 15, 0, 0) self._layout.addLayout(self._sub_layout, self._layout.rowCount() + 2, 0, 1, 2) def _on_command_type_change(self, text: str): """Handles the command type combobox change event.""" if text == "Module": self.set_module_layout() else: self.set_shell_layout() def _on_module_change(self, module_name: str): """Handles module combobox changes.""" while self._sub_layout.count(): child = self._sub_layout.takeAt(0) if child.widget(): child.widget().deleteLater() cached_module = modules.get_module(module_name) if not cached_module: cached_module = modules.load_module(module_name, self._module_view, self._model) input_fields = [] for option_name in cached_module.get_setup_messages(): input_field = QLineEdit() input_fields.append(input_field) self._sub_layout.addWidget(QLabel(option_name)) self._sub_layout.addWidget(input_field) run_button = QPushButton("Run") run_button.setMaximumWidth(250) run_button.setMinimumHeight(25) run_button.pressed.connect( lambda: self._on_module_run(module_name, input_fields)) self._sub_layout.addWidget(QLabel("")) self._sub_layout.addWidget(run_button) self._sub_layout.setContentsMargins(0, 15, 0, 0) def display_info(self, text: str): message_box = QMessageBox() message_box.setIcon(QMessageBox.Information) message_box.setWindowTitle("Information") message_box.setText(text) message_box.setStandardButtons(QMessageBox.Ok) message_box.exec_() def _on_module_run(self, module_name: str, input_fields: list): """Handles running modules.""" set_options = [] for input_field in input_fields: set_options.append(input_field.text()) module = modules.get_module(module_name) if not module: module = modules.load_module(module_name, self._module_view, self._model) successful, options = module.setup(set_options) if successful: if module_name == "remove_bot": code = loaders.get_remove_code(self._current_bot.loader_name) elif module_name == "update_bot": code = loaders.get_update_code(self._current_bot.loader_name) else: code = modules.get_code(module_name) if not options: options = {} options["module_name"] = module_name self._model.add_command(self._current_bot.uid, Command(CommandType.MODULE, code, options)) self.display_info("Module added to the queue of:\n {}@{}".format( self._current_bot.username, self._current_bot.hostname)) def _on_command_run(self, command_input: QLineEdit): """Handles running commands.""" if command_input.text().strip() == "": return self._model.add_command( self._current_bot.uid, Command(CommandType.SHELL, command_input.text().encode())) command_input.clear() self.display_info("Command added to the queue of:\n {}@{}".format( self._current_bot.username, self._current_bot.hostname))
class ConfigWidget(QWidget, Logger): ''' Config dialog for Marvin Manager ''' WIZARD_PROFILES = { 'Annotations': { 'label': 'mm_annotations', 'datatype': 'comments', 'display': {}, 'is_multiple': False }, 'Collections': { 'label': 'mm_collections', 'datatype': 'text', 'display': {u'is_names': False}, 'is_multiple': True }, 'Last read': { 'label': 'mm_date_read', 'datatype': 'datetime', 'display': {}, 'is_multiple': False }, 'Locked': { 'label': 'mm_locked', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Progress': { 'label': 'mm_progress', 'datatype': 'float', 'display': {u'number_format': u'{0:.0f}%'}, 'is_multiple': False }, 'Read': { 'label': 'mm_read', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Reading list': { 'label': 'mm_reading_list', 'datatype': 'bool', 'display': {}, 'is_multiple': False }, 'Word count': { 'label': 'mm_word_count', 'datatype': 'int', 'display': {u'number_format': u'{0:n}'}, 'is_multiple': False } } def __init__(self, plugin_action): QWidget.__init__(self) self.parent = plugin_action self.gui = get_gui() self.icon = plugin_action.icon self.opts = plugin_action.opts self.prefs = plugin_prefs self.resources_path = plugin_action.resources_path self.verbose = plugin_action.verbose self.restart_required = False self._log_location() self.l = QGridLayout() self.setLayout(self.l) self.column1_layout = QVBoxLayout() self.l.addLayout(self.column1_layout, 0, 0) self.column2_layout = QVBoxLayout() self.l.addLayout(self.column2_layout, 0, 1) # ----------------------------- Column 1 ----------------------------- # ~~~~~~~~ Create the Custom fields options group box ~~~~~~~~ self.cfg_custom_fields_gb = QGroupBox(self) self.cfg_custom_fields_gb.setTitle('Custom column assignments') self.column1_layout.addWidget(self.cfg_custom_fields_gb) self.cfg_custom_fields_qgl = QGridLayout(self.cfg_custom_fields_gb) current_row = 0 # ++++++++ Labels + HLine ++++++++ self.marvin_source_label = QLabel("Marvin source") self.cfg_custom_fields_qgl.addWidget(self.marvin_source_label, current_row, 0) self.calibre_destination_label = QLabel("calibre destination") self.cfg_custom_fields_qgl.addWidget(self.calibre_destination_label, current_row, 1) current_row += 1 self.sd_hl = QFrame(self.cfg_custom_fields_gb) self.sd_hl.setFrameShape(QFrame.HLine) self.sd_hl.setFrameShadow(QFrame.Raised) self.cfg_custom_fields_qgl.addWidget(self.sd_hl, current_row, 0, 1, 3) current_row += 1 # ++++++++ Annotations ++++++++ self.cfg_annotations_label = QLabel('Annotations') self.cfg_annotations_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_annotations_label, current_row, 0) self.annotations_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.annotations_field_comboBox.setObjectName('annotations_field_comboBox') self.annotations_field_comboBox.setToolTip('Select a custom column to store Marvin annotations') self.cfg_custom_fields_qgl.addWidget(self.annotations_field_comboBox, current_row, 1) self.cfg_highlights_wizard = QToolButton() self.cfg_highlights_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_highlights_wizard.setToolTip("Create a custom column to store Marvin annotations") self.cfg_highlights_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Annotations')) self.cfg_custom_fields_qgl.addWidget(self.cfg_highlights_wizard, current_row, 2) current_row += 1 # ++++++++ Collections ++++++++ self.cfg_collections_label = QLabel('Collections') self.cfg_collections_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_label, current_row, 0) self.collection_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.collection_field_comboBox.setObjectName('collection_field_comboBox') self.collection_field_comboBox.setToolTip('Select a custom column to store Marvin collection assignments') self.cfg_custom_fields_qgl.addWidget(self.collection_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column for Marvin collection assignments") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Collections')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Last read ++++++++ self.cfg_date_read_label = QLabel("Last read") self.cfg_date_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_date_read_label, current_row, 0) self.date_read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.date_read_field_comboBox.setObjectName('date_read_field_comboBox') self.date_read_field_comboBox.setToolTip('Select a custom column to store Last read date') self.cfg_custom_fields_qgl.addWidget(self.date_read_field_comboBox, current_row, 1) self.cfg_collections_wizard = QToolButton() self.cfg_collections_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_collections_wizard.setToolTip("Create a custom column to store Last read date") self.cfg_collections_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Last read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_collections_wizard, current_row, 2) current_row += 1 # ++++++++ Locked ++++++++ self.cfg_locked_label = QLabel("Locked") self.cfg_locked_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_label, current_row, 0) self.locked_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.locked_field_comboBox.setObjectName('locked_field_comboBox') self.locked_field_comboBox.setToolTip('Select a custom column to store Locked status') self.cfg_custom_fields_qgl.addWidget(self.locked_field_comboBox, current_row, 1) self.cfg_locked_wizard = QToolButton() self.cfg_locked_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_locked_wizard.setToolTip("Create a custom column to store Locked status") self.cfg_locked_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Locked')) self.cfg_custom_fields_qgl.addWidget(self.cfg_locked_wizard, current_row, 2) current_row += 1 # ++++++++ Progress ++++++++ self.cfg_progress_label = QLabel('Progress') self.cfg_progress_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_label, current_row, 0) self.progress_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.progress_field_comboBox.setObjectName('progress_field_comboBox') self.progress_field_comboBox.setToolTip('Select a custom column to store Marvin reading progress') self.cfg_custom_fields_qgl.addWidget(self.progress_field_comboBox, current_row, 1) self.cfg_progress_wizard = QToolButton() self.cfg_progress_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_progress_wizard.setToolTip("Create a custom column to store Marvin reading progress") self.cfg_progress_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Progress')) self.cfg_custom_fields_qgl.addWidget(self.cfg_progress_wizard, current_row, 2) current_row += 1 # ++++++++ Read flag ++++++++ self.cfg_read_label = QLabel('Read') self.cfg_read_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_label, current_row, 0) self.read_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.read_field_comboBox.setObjectName('read_field_comboBox') self.read_field_comboBox.setToolTip('Select a custom column to store Marvin Read status') self.cfg_custom_fields_qgl.addWidget(self.read_field_comboBox, current_row, 1) self.cfg_read_wizard = QToolButton() self.cfg_read_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_read_wizard.setToolTip("Create a custom column to store Marvin Read status") self.cfg_read_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Read')) self.cfg_custom_fields_qgl.addWidget(self.cfg_read_wizard, current_row, 2) current_row += 1 # ++++++++ Reading list flag ++++++++ self.cfg_reading_list_label = QLabel('Reading list') self.cfg_reading_list_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_label, current_row, 0) self.reading_list_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.reading_list_field_comboBox.setObjectName('reading_list_field_comboBox') self.reading_list_field_comboBox.setToolTip('Select a custom column to store Marvin Reading list status') self.cfg_custom_fields_qgl.addWidget(self.reading_list_field_comboBox, current_row, 1) self.cfg_reading_list_wizard = QToolButton() self.cfg_reading_list_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_reading_list_wizard.setToolTip("Create a custom column to store Marvin Reading list status") self.cfg_reading_list_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Reading list')) self.cfg_custom_fields_qgl.addWidget(self.cfg_reading_list_wizard, current_row, 2) current_row += 1 # ++++++++ Word count ++++++++ self.cfg_word_count_label = QLabel('Word count') self.cfg_word_count_label.setAlignment(Qt.AlignLeft) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_label, current_row, 0) self.word_count_field_comboBox = QComboBox(self.cfg_custom_fields_gb) self.word_count_field_comboBox.setObjectName('word_count_field_comboBox') self.word_count_field_comboBox.setToolTip('Select a custom column to store Marvin word counts') self.cfg_custom_fields_qgl.addWidget(self.word_count_field_comboBox, current_row, 1) self.cfg_word_count_wizard = QToolButton() self.cfg_word_count_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_word_count_wizard.setToolTip("Create a custom column to store Marvin word counts") self.cfg_word_count_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Word count')) self.cfg_custom_fields_qgl.addWidget(self.cfg_word_count_wizard, current_row, 2) current_row += 1 self.spacerItem1 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column1_layout.addItem(self.spacerItem1) # ----------------------------- Column 2 ----------------------------- # ~~~~~~~~ Create the CSS group box ~~~~~~~~ self.cfg_css_options_gb = QGroupBox(self) self.cfg_css_options_gb.setTitle('CSS') self.column2_layout.addWidget(self.cfg_css_options_gb) self.cfg_css_options_qgl = QGridLayout(self.cfg_css_options_gb) current_row = 0 # ++++++++ Annotations appearance ++++++++ self.annotations_icon = QIcon(os.path.join(self.resources_path, 'icons', 'annotations_hiliter.png')) self.cfg_annotations_appearance_toolbutton = QToolButton() self.cfg_annotations_appearance_toolbutton.setIcon(self.annotations_icon) self.cfg_annotations_appearance_toolbutton.clicked.connect(self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_appearance_toolbutton, current_row, 0) self.cfg_annotations_label = ClickableQLabel("Book notes, Bookmark notes and Annotations") self.cfg_annotations_label.clicked.connect(self.configure_appearance) self.cfg_css_options_qgl.addWidget(self.cfg_annotations_label, current_row, 1) current_row += 1 # ++++++++ Injected CSS ++++++++ self.css_editor_icon = QIcon(I('format-text-heading.png')) self.cfg_css_editor_toolbutton = QToolButton() self.cfg_css_editor_toolbutton.setIcon(self.css_editor_icon) self.cfg_css_editor_toolbutton.clicked.connect(self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_toolbutton, current_row, 0) self.cfg_css_editor_label = ClickableQLabel("Articles, Vocabulary") self.cfg_css_editor_label.clicked.connect(self.edit_css) self.cfg_css_options_qgl.addWidget(self.cfg_css_editor_label, current_row, 1) """ # ~~~~~~~~ Create the Dropbox syncing group box ~~~~~~~~ self.cfg_dropbox_syncing_gb = QGroupBox(self) self.cfg_dropbox_syncing_gb.setTitle('Dropbox') self.column2_layout.addWidget(self.cfg_dropbox_syncing_gb) self.cfg_dropbox_syncing_qgl = QGridLayout(self.cfg_dropbox_syncing_gb) current_row = 0 # ++++++++ Syncing enabled checkbox ++++++++ self.dropbox_syncing_checkbox = QCheckBox('Enable Dropbox updates') self.dropbox_syncing_checkbox.setObjectName('dropbox_syncing') self.dropbox_syncing_checkbox.setToolTip('Refresh custom column content from Marvin metadata') self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_syncing_checkbox, current_row, 0, 1, 3) current_row += 1 # ++++++++ Dropbox folder picker ++++++++ self.dropbox_folder_icon = QIcon(os.path.join(self.resources_path, 'icons', 'dropbox.png')) self.cfg_dropbox_folder_toolbutton = QToolButton() self.cfg_dropbox_folder_toolbutton.setIcon(self.dropbox_folder_icon) self.cfg_dropbox_folder_toolbutton.setToolTip("Specify Dropbox folder location on your computer") self.cfg_dropbox_folder_toolbutton.clicked.connect(self.select_dropbox_folder) self.cfg_dropbox_syncing_qgl.addWidget(self.cfg_dropbox_folder_toolbutton, current_row, 1) # ++++++++ Dropbox location lineedit ++++++++ self.dropbox_location_lineedit = QLineEdit() self.dropbox_location_lineedit.setPlaceholderText("Dropbox folder location") self.cfg_dropbox_syncing_qgl.addWidget(self.dropbox_location_lineedit, current_row, 2) """ # ~~~~~~~~ Create the General options group box ~~~~~~~~ self.cfg_runtime_options_gb = QGroupBox(self) self.cfg_runtime_options_gb.setTitle('General options') self.column2_layout.addWidget(self.cfg_runtime_options_gb) self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb) # ++++++++ Temporary markers: Duplicates ++++++++ self.duplicate_markers_checkbox = QCheckBox('Apply temporary markers to duplicate books') self.duplicate_markers_checkbox.setObjectName('apply_markers_to_duplicates') self.duplicate_markers_checkbox.setToolTip('Books with identical content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.duplicate_markers_checkbox) # ++++++++ Temporary markers: Updated ++++++++ self.updated_markers_checkbox = QCheckBox('Apply temporary markers to books with updated content') self.updated_markers_checkbox.setObjectName('apply_markers_to_updated') self.updated_markers_checkbox.setToolTip('Books with updated content will be flagged in the Library window') self.cfg_runtime_options_qvl.addWidget(self.updated_markers_checkbox) # ++++++++ Auto refresh checkbox ++++++++ self.auto_refresh_checkbox = QCheckBox('Automatically refresh custom column content') self.auto_refresh_checkbox.setObjectName('auto_refresh_at_startup') self.auto_refresh_checkbox.setToolTip('Update calibre custom column when Marvin XD is opened') self.cfg_runtime_options_qvl.addWidget(self.auto_refresh_checkbox) # ++++++++ Progress as percentage checkbox ++++++++ self.reading_progress_checkbox = QCheckBox('Show reading progress as percentage') self.reading_progress_checkbox.setObjectName('show_progress_as_percentage') self.reading_progress_checkbox.setToolTip('Display percentage in Progress column') self.cfg_runtime_options_qvl.addWidget(self.reading_progress_checkbox) # ~~~~~~~~ Create the Debug options group box ~~~~~~~~ self.cfg_debug_options_gb = QGroupBox(self) self.cfg_debug_options_gb.setTitle('Debug options') self.column2_layout.addWidget(self.cfg_debug_options_gb) self.cfg_debug_options_qvl = QVBoxLayout(self.cfg_debug_options_gb) # ++++++++ Debug logging checkboxes ++++++++ self.debug_plugin_checkbox = QCheckBox('Enable debug logging for Marvin XD') self.debug_plugin_checkbox.setObjectName('debug_plugin_checkbox') self.debug_plugin_checkbox.setToolTip('Print plugin diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_plugin_checkbox) self.debug_libimobiledevice_checkbox = QCheckBox('Enable debug logging for libiMobileDevice') self.debug_libimobiledevice_checkbox.setObjectName('debug_libimobiledevice_checkbox') self.debug_libimobiledevice_checkbox.setToolTip('Print libiMobileDevice diagnostic messages to console') self.cfg_debug_options_qvl.addWidget(self.debug_libimobiledevice_checkbox) self.spacerItem2 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.column2_layout.addItem(self.spacerItem2) # ~~~~~~~~ End of construction zone ~~~~~~~~ self.resize(self.sizeHint()) # ~~~~~~~~ Populate/restore config options ~~~~~~~~ # Annotations comboBox self.populate_annotations() self.populate_collections() self.populate_date_read() self.populate_locked() self.populate_progress() self.populate_read() self.populate_reading_list() self.populate_word_count() """ # Restore Dropbox settings, hook changes dropbox_syncing = self.prefs.get('dropbox_syncing', False) self.dropbox_syncing_checkbox.setChecked(dropbox_syncing) self.set_dropbox_syncing(dropbox_syncing) self.dropbox_syncing_checkbox.clicked.connect(partial(self.set_dropbox_syncing)) self.dropbox_location_lineedit.setText(self.prefs.get('dropbox_folder', '')) """ # Restore general settings self.duplicate_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_duplicates', True)) self.updated_markers_checkbox.setChecked(self.prefs.get('apply_markers_to_updated', True)) self.auto_refresh_checkbox.setChecked(self.prefs.get('auto_refresh_at_startup', False)) self.reading_progress_checkbox.setChecked(self.prefs.get('show_progress_as_percentage', False)) # Restore debug settings, hook changes self.debug_plugin_checkbox.setChecked(self.prefs.get('debug_plugin', False)) self.debug_plugin_checkbox.stateChanged.connect(self.set_restart_required) self.debug_libimobiledevice_checkbox.setChecked(self.prefs.get('debug_libimobiledevice', False)) self.debug_libimobiledevice_checkbox.stateChanged.connect(self.set_restart_required) # Hook changes to Annotations comboBox # self.annotations_field_comboBox.currentIndexChanged.connect( # partial(self.save_combobox_setting, 'annotations_field_comboBox')) # self.connect(self.annotations_field_comboBox, # SIGNAL('currentIndexChanged(const QString &)'), # self.annotations_destination_changed) self.annotations_field_comboBox.currentIndexChanged.connect(self.annotations_destination_changed) # Launch the annotated_books_scanner field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field) self.annotated_books_scanner.signal.connect(self.inventory_complete) QTimer.singleShot(1, self.start_inventory) def annotations_destination_changed(self, qs_new_destination_name): ''' If the destination field changes, move all existing annotations from old to new ''' self._log_location(str(qs_new_destination_name)) self._log("self.eligible_annotations_fields: %s" % self.eligible_annotations_fields) old_destination_field = get_cc_mapping('annotations', 'field', None) old_destination_name = get_cc_mapping('annotations', 'combobox', None) self._log("old_destination_field: %s" % old_destination_field) self._log("old_destination_name: %s" % old_destination_name) # new_destination_name = unicode(qs_new_destination_name) # Signnls available have changed. Now receivin an indec rather than a name. Can get the name # from the combobox new_destination_name = unicode(self.annotations_field_comboBox.currentText()) self._log("new_destination_name: %s" % repr(new_destination_name)) if old_destination_name == new_destination_name: self._log_location("old_destination_name = new_destination_name, no changes") return if new_destination_name == '': self._log_location("annotations storage disabled") set_cc_mapping('annotations', field=None, combobox=new_destination_name) return new_destination_field = self.eligible_annotations_fields[new_destination_name] if existing_annotations(self.parent, old_destination_field): command = self.launch_new_destination_dialog(old_destination_name, new_destination_name) if command == 'move': set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name) if self.annotated_books_scanner.isRunning(): self.annotated_books_scanner.wait() move_annotations(self, self.annotated_books_scanner.annotation_map, old_destination_field, new_destination_field) elif command == 'change': # Keep the updated destination field, but don't move annotations pass elif command == 'cancel': # Restore previous destination self.annotations_field_comboBox.blockSignals(True) old_index = self.annotations_field_comboBox.findText(old_destination_name) self.annotations_field_comboBox.setCurrentIndex(old_index) self.annotations_field_comboBox.blockSignals(False) else: # No existing annotations, just update prefs self._log("no existing annotations, updating destination to '{0}'".format(new_destination_name)) set_cc_mapping('annotations', field=new_destination_field, combobox=new_destination_name) def configure_appearance(self): ''' ''' self._log_location() appearance_settings = { 'appearance_css': default_elements, 'appearance_hr_checkbox': False, 'appearance_timestamp_format': default_timestamp } # Save, hash the original settings original_settings = {} osh = hashlib.md5() for setting in appearance_settings: original_settings[setting] = plugin_prefs.get(setting, appearance_settings[setting]) osh.update(repr(plugin_prefs.get(setting, appearance_settings[setting]))) # Display the Annotations appearance dialog aa = AnnotationsAppearance(self, self.annotations_icon, plugin_prefs) cancelled = False if aa.exec_(): # appearance_hr_checkbox and appearance_timestamp_format changed live to prefs during previews plugin_prefs.set('appearance_css', aa.elements_table.get_data()) # Generate a new hash nsh = hashlib.md5() for setting in appearance_settings: nsh.update(repr(plugin_prefs.get(setting, appearance_settings[setting]))) else: for setting in appearance_settings: plugin_prefs.set(setting, original_settings[setting]) nsh = osh # If there were changes, and there are existing annotations, # and there is an active Annotations field, offer to re-render field = get_cc_mapping('annotations', 'field', None) if osh.digest() != nsh.digest() and existing_annotations(self.parent, field): title = 'Update annotations?' msg = '<p>Update existing annotations to new appearance settings?</p>' d = MessageBox(MessageBox.QUESTION, title, msg, show_copy_button=False) self._log_location("QUESTION: %s" % msg) if d.exec_(): self._log_location("Updating existing annotations to modified appearance") # Wait for indexing to complete while not self.annotated_books_scanner.isFinished(): Application.processEvents() move_annotations(self, self.annotated_books_scanner.annotation_map, field, field, window_title="Updating appearance") def edit_css(self): ''' ''' self._log_location() from calibre_plugins.marvin_manager.book_status import dialog_resources_path klass = os.path.join(dialog_resources_path, 'css_editor.py') if os.path.exists(klass): sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('css_editor') sys.path.remove(dialog_resources_path) dlg = this_dc.CSSEditorDialog(self, 'css_editor') dlg.initialize(self) dlg.exec_() def get_eligible_custom_fields(self, eligible_types=[], is_multiple=None): ''' Discover qualifying custom fields for eligible_types[] ''' #self._log_location(eligible_types) eligible_custom_fields = {} for cf in self.gui.current_db.custom_field_keys(): cft = self.gui.current_db.metadata_for_field(cf)['datatype'] cfn = self.gui.current_db.metadata_for_field(cf)['name'] cfim = self.gui.current_db.metadata_for_field(cf)['is_multiple'] #self._log("cf: %s cft: %s cfn: %s cfim: %s" % (cf, cft, cfn, cfim)) if cft in eligible_types: if is_multiple is not None: if bool(cfim) == is_multiple: eligible_custom_fields[cfn] = cf else: eligible_custom_fields[cfn] = cf return eligible_custom_fields def inventory_complete(self, msg): self._log_location(msg) def launch_cc_wizard(self, column_type): ''' ''' def _update_combo_box(comboBox, destination, previous): ''' ''' cb = getattr(self, comboBox) cb.blockSignals(True) all_items = [str(cb.itemText(i)) for i in range(cb.count())] if previous and previous in all_items: all_items.remove(previous) all_items.append(destination) cb.clear() cb.addItems(sorted(all_items, key=lambda s: s.lower())) # Select the new destination in the comboBox idx = cb.findText(destination) if idx > -1: cb.setCurrentIndex(idx) cb.blockSignals(False) from calibre_plugins.marvin_manager.book_status import dialog_resources_path klass = os.path.join(dialog_resources_path, 'cc_wizard.py') if os.path.exists(klass): #self._log("importing CC Wizard dialog from '%s'" % klass) sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('cc_wizard') sys.path.remove(dialog_resources_path) dlg = this_dc.CustomColumnWizard(self, column_type, self.WIZARD_PROFILES[column_type], verbose=True) dlg.exec_() if dlg.modified_column: self._log("modified_column: %s" % dlg.modified_column) self.restart_required = True destination = dlg.modified_column['destination'] label = dlg.modified_column['label'] previous = dlg.modified_column['previous'] source = dlg.modified_column['source'] if source == "Annotations": _update_combo_box("annotations_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_annotations_fields[destination] = label # Save manually in case user cancels set_cc_mapping('annotations', combobox=destination, field=label) elif source == 'Collections': _update_combo_box("collection_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_collection_fields[destination] = label # Save manually in case user cancels set_cc_mapping('collections', combobox=destination, field=label) elif source == 'Last read': _update_combo_box("date_read_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_date_read_fields[destination] = label # Save manually in case user cancels set_cc_mapping('date_read', combobox=destination, field=label) elif source == 'Locked': _update_combo_box("locked_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_locked_fields[destination] = label # Save manually in case user cancels set_cc_mapping('locked', combobox=destination, field=label) elif source == "Progress": _update_combo_box("progress_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_progress_fields[destination] = label # Save manually in case user cancels set_cc_mapping('progress', combobox=destination, field=label) elif source == "Read": _update_combo_box("read_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_read_fields[destination] = label # Save manually in case user cancels set_cc_mapping('read', combobox=destination, field=label) elif source == "Reading list": _update_combo_box("reading_list_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_reading_list_fields[destination] = label # Save manually in case user cancels set_cc_mapping('reading_list', combobox=destination, field=label) elif source == "Word count": _update_combo_box("word_count_field_comboBox", destination, previous) # Add/update the new destination so save_settings() can find it self.eligible_word_count_fields[destination] = label # Save manually in case user cancels set_cc_mapping('word_count', combobox=destination, field=label) else: self._log("ERROR: Can't import from '%s'" % klass) def launch_new_destination_dialog(self, old, new): ''' Return 'move', 'change' or 'cancel' ''' from calibre_plugins.marvin_manager.book_status import dialog_resources_path self._log_location() klass = os.path.join(dialog_resources_path, 'new_destination.py') if os.path.exists(klass): self._log("importing new destination dialog from '%s'" % klass) sys.path.insert(0, dialog_resources_path) this_dc = importlib.import_module('new_destination') sys.path.remove(dialog_resources_path) dlg = this_dc.NewDestinationDialog(self, old, new) dlg.exec_() return dlg.command def populate_annotations(self): datatype = self.WIZARD_PROFILES['Annotations']['datatype'] self.eligible_annotations_fields = self.get_eligible_custom_fields([datatype]) self.annotations_field_comboBox.addItems(['']) ecf = sorted(self.eligible_annotations_fields.keys(), key=lambda s: s.lower()) self.annotations_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('annotations', 'combobox') if existing: ci = self.annotations_field_comboBox.findText(existing) self.annotations_field_comboBox.setCurrentIndex(ci) def populate_collections(self): datatype = self.WIZARD_PROFILES['Collections']['datatype'] self.eligible_collection_fields = self.get_eligible_custom_fields([datatype], is_multiple=True) self.collection_field_comboBox.addItems(['']) ecf = sorted(self.eligible_collection_fields.keys(), key=lambda s: s.lower()) self.collection_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('collections', 'combobox') if existing: ci = self.collection_field_comboBox.findText(existing) self.collection_field_comboBox.setCurrentIndex(ci) def populate_date_read(self): #self.eligible_date_read_fields = self.get_eligible_custom_fields(['datetime']) datatype = self.WIZARD_PROFILES['Last read']['datatype'] self.eligible_date_read_fields = self.get_eligible_custom_fields([datatype]) self.date_read_field_comboBox.addItems(['']) ecf = sorted(self.eligible_date_read_fields.keys(), key=lambda s: s.lower()) self.date_read_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('date_read', 'combobox') if existing: ci = self.date_read_field_comboBox.findText(existing) self.date_read_field_comboBox.setCurrentIndex(ci) def populate_locked(self): datatype = self.WIZARD_PROFILES['Locked']['datatype'] self.eligible_locked_fields = self.get_eligible_custom_fields([datatype]) self.locked_field_comboBox.addItems(['']) ecf = sorted(self.eligible_locked_fields.keys(), key=lambda s: s.lower()) self.locked_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('locked', 'combobox') if existing: ci = self.locked_field_comboBox.findText(existing) self.locked_field_comboBox.setCurrentIndex(ci) def populate_progress(self): #self.eligible_progress_fields = self.get_eligible_custom_fields(['float']) datatype = self.WIZARD_PROFILES['Progress']['datatype'] self.eligible_progress_fields = self.get_eligible_custom_fields([datatype]) self.progress_field_comboBox.addItems(['']) ecf = sorted(self.eligible_progress_fields.keys(), key=lambda s: s.lower()) self.progress_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('progress', 'combobox') if existing: ci = self.progress_field_comboBox.findText(existing) self.progress_field_comboBox.setCurrentIndex(ci) def populate_read(self): datatype = self.WIZARD_PROFILES['Read']['datatype'] self.eligible_read_fields = self.get_eligible_custom_fields([datatype]) self.read_field_comboBox.addItems(['']) ecf = sorted(self.eligible_read_fields.keys(), key=lambda s: s.lower()) self.read_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('read', 'combobox') if existing: ci = self.read_field_comboBox.findText(existing) self.read_field_comboBox.setCurrentIndex(ci) def populate_reading_list(self): datatype = self.WIZARD_PROFILES['Reading list']['datatype'] self.eligible_reading_list_fields = self.get_eligible_custom_fields([datatype]) self.reading_list_field_comboBox.addItems(['']) ecf = sorted(self.eligible_reading_list_fields.keys(), key=lambda s: s.lower()) self.reading_list_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('reading_list', 'combobox') if existing: ci = self.reading_list_field_comboBox.findText(existing) self.reading_list_field_comboBox.setCurrentIndex(ci) def populate_word_count(self): #self.eligible_word_count_fields = self.get_eligible_custom_fields(['int']) datatype = self.WIZARD_PROFILES['Word count']['datatype'] self.eligible_word_count_fields = self.get_eligible_custom_fields([datatype]) self.word_count_field_comboBox.addItems(['']) ecf = sorted(self.eligible_word_count_fields.keys(), key=lambda s: s.lower()) self.word_count_field_comboBox.addItems(ecf) # Retrieve stored value existing = get_cc_mapping('word_count', 'combobox') if existing: ci = self.word_count_field_comboBox.findText(existing) self.word_count_field_comboBox.setCurrentIndex(ci) """ def select_dropbox_folder(self): ''' ''' self._log_location() dropbox_location = QFileDialog.getExistingDirectory( self, "Dropbox folder", os.path.expanduser("~"), QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) self.dropbox_location_lineedit.setText(unicode(dropbox_location)) def set_dropbox_syncing(self, state): ''' Called when checkbox changes state, or when restoring state Set enabled state of Dropbox folder picker to match ''' self.cfg_dropbox_folder_toolbutton.setEnabled(state) self.dropbox_location_lineedit.setEnabled(state) """ def set_restart_required(self, state): ''' Set restart_required flag to show show dialog when closing dialog ''' self.restart_required = True """ def save_combobox_setting(self, cb, index): ''' Apply changes immediately ''' cf = str(getattr(self, cb).currentText()) self._log_location("%s => %s" % (cb, repr(cf))) if cb == 'annotations_field_comboBox': field = None if cf: field = self.eligible_annotations_fields[cf] set_cc_mapping('annotations', combobox=cf, field=field) """ def save_settings(self): self._log_location() # Annotations field cf = unicode(self.annotations_field_comboBox.currentText()) field = None if cf: field = self.eligible_annotations_fields[cf] set_cc_mapping('annotations', combobox=cf, field=field) # Collections field cf = unicode(self.collection_field_comboBox.currentText()) field = None if cf: field = self.eligible_collection_fields[cf] set_cc_mapping('collections', combobox=cf, field=field) # Date read field cf = unicode(self.date_read_field_comboBox.currentText()) field = None if cf: field = self.eligible_date_read_fields[cf] set_cc_mapping('date_read', combobox=cf, field=field) # Locked field cf = unicode(self.locked_field_comboBox.currentText()) field = None if cf: field = self.eligible_locked_fields[cf] set_cc_mapping('locked', combobox=cf, field=field) # Progress field cf = unicode(self.progress_field_comboBox.currentText()) field = None if cf: field = self.eligible_progress_fields[cf] set_cc_mapping('progress', combobox=cf, field=field) # Read field cf = unicode(self.read_field_comboBox.currentText()) field = None if cf: field = self.eligible_read_fields[cf] set_cc_mapping('read', combobox=cf, field=field) # Reading list field cf = unicode(self.reading_list_field_comboBox.currentText()) field = None if cf: field = self.eligible_reading_list_fields[cf] set_cc_mapping('reading_list', combobox=cf, field=field) # Word count field cf = unicode(self.word_count_field_comboBox.currentText()) field = None if cf: field = self.eligible_word_count_fields[cf] set_cc_mapping('word_count', combobox=cf, field=field) ''' # Save Dropbox settings self.prefs.set('dropbox_syncing', self.dropbox_syncing_checkbox.isChecked()) self.prefs.set('dropbox_folder', unicode(self.dropbox_location_lineedit.text())) ''' # Save general settings self.prefs.set('apply_markers_to_duplicates', self.duplicate_markers_checkbox.isChecked()) self.prefs.set('apply_markers_to_updated', self.updated_markers_checkbox.isChecked()) self.prefs.set('auto_refresh_at_startup', self.auto_refresh_checkbox.isChecked()) self.prefs.set('show_progress_as_percentage', self.reading_progress_checkbox.isChecked()) # Save debug settings self.prefs.set('debug_plugin', self.debug_plugin_checkbox.isChecked()) self.prefs.set('debug_libimobiledevice', self.debug_libimobiledevice_checkbox.isChecked()) # If restart needed, inform user if self.restart_required: do_restart = show_restart_warning('Restart calibre for the changes to be applied.', parent=self.gui) if do_restart: self.gui.quit(restart=True) def start_inventory(self): self._log_location() self.annotated_books_scanner.start()
class LLT_ConjAdd(QMainWindow): def __init__(self): super(LLT_ConjAdd, self).__init__() self.w = QWidget() self.setCentralWidget(self.w) #construct GUI self.setWindowTitle("Verb Conjugations") self.setGeometry(0, 0, 900, 600) self.conjDicList = [] self.wordList = [] self.newDic = {'INF': '', 'IND': '', 'SUB': '', 'IMP': ''} self.headingLab = QLabel("Add New Conjugation Table") self.wordInfLab = QLabel("Infinitive") self.wordInfLab.setAlignment(Qt.AlignRight) self.infEntry = QLineEdit() #INDICATIVE FORM TABLE self.indLab = QLabel("Indicative") self.indYoLab = QLabel("Yo") self.indYoLab.setAlignment(Qt.AlignRight) self.indTuLab = QLabel("Tú") self.indTuLab.setAlignment(Qt.AlignRight) self.indUstLab = QLabel("Él/la, Ud") self.indUstLab.setAlignment(Qt.AlignRight) self.indNosLab = QLabel("Nosotros") self.indNosLab.setAlignment(Qt.AlignRight) self.indUstdsLab = QLabel("Ellos/as, Uds") self.indUstdsLab.setAlignment(Qt.AlignRight) self.indPresLab = QLabel("Present") self.indPretLab = QLabel("Preterite") self.indImpLab = QLabel("Imperfect") self.indFutLab = QLabel("Future") self.indCondLab = QLabel("Conditional") self.entryGridInd = QGridLayout() for i in range(5): for j in range(5): self.entry = QLineEdit() self.entryGridInd.addWidget(self.entry, i, j) #SUBJUNCTIVE FORM TABLE self.subLab = QLabel("Subjunctive") self.subYoLab = QLabel("Yo") self.subYoLab.setAlignment(Qt.AlignRight) self.subTuLab = QLabel("Tú") self.subTuLab.setAlignment(Qt.AlignRight) self.subUstLab = QLabel("Él/la, Ud") self.subUstLab.setAlignment(Qt.AlignRight) self.subNosLab = QLabel("Nosotros/as") self.subNosLab.setAlignment(Qt.AlignRight) self.subUstdsLab = QLabel("Ellos/as, Uds") self.subUstdsLab.setAlignment(Qt.AlignRight) self.subPresLab = QLabel("Present") self.subImpLab = QLabel("Imperfect") self.subFutLab = QLabel("Future") self.entryGridSub = QGridLayout() for i in range(5): for j in range(3): self.entry = QLineEdit() self.entryGridSub.addWidget(self.entry, i, j) #IMPERATIVE FORM TABLE self.impvLab = QLabel("Imperative") self.impvTu = QLabel("Tú") self.impvTu.setAlignment(Qt.AlignRight) self.impvUd = QLabel("Usted") self.impvUd.setAlignment(Qt.AlignRight) self.impvNos = QLabel("Nosotros/as") self.impvNos.setAlignment(Qt.AlignRight) self.impvUdes = QLabel("Ustedes") self.impvUdes.setAlignment(Qt.AlignRight) self.impvAffLab = QLabel("Affirmative") self.impvNegLab = QLabel("Negative") self.entryGridImpv = QGridLayout() for i in range(4): for j in range(2): self.entry = QLineEdit() self.entryGridImpv.addWidget(self.entry, i, j) self.checkBut = QPushButton("Check") self.checkBut.clicked.connect(self.check) self.saveBut = QPushButton("Save") self.saveBut.clicked.connect(self.save) self.newBut = QPushButton("New Word") self.newBut.clicked.connect(self.new) self.clearBut = QPushButton("Clear") self.clearBut.clicked.connect(self.clear) self.quitBut = QPushButton("Quit") self.quitBut.clicked.connect(self.quit) self.theGrid = QGridLayout() self.theGrid.addWidget(self.headingLab, 0, 0) self.theGrid.addWidget(self.wordInfLab, 1, 0) self.theGrid.addWidget(self.infEntry, 1, 1) self.theGrid.addWidget(self.indLab, 3, 0) self.theGrid.addWidget(self.indPresLab, 3, 1) self.theGrid.addWidget(self.indPretLab, 3, 2) self.theGrid.addWidget(self.indImpLab, 3, 3) self.theGrid.addWidget(self.indFutLab, 3, 4) self.theGrid.addWidget(self.indCondLab, 3, 5) self.theGrid.addWidget(self.indYoLab, 4, 0) self.theGrid.addWidget(self.indTuLab, 5, 0) self.theGrid.addWidget(self.indUstLab, 6, 0) self.theGrid.addWidget(self.indNosLab, 7, 0) self.theGrid.addWidget(self.indUstdsLab, 8, 0) self.theGrid.addLayout(self.entryGridInd, 4, 1, 5, 5) self.theGrid.addWidget(self.subLab, 11, 0) self.theGrid.addWidget(self.subPresLab, 11, 1) self.theGrid.addWidget(self.subImpLab, 11, 2) self.theGrid.addWidget(self.subFutLab, 11, 3) self.theGrid.addWidget(self.subYoLab, 12, 0) self.theGrid.addWidget(self.subTuLab, 13, 0) self.theGrid.addWidget(self.subUstLab, 14, 0) self.theGrid.addWidget(self.subNosLab, 15, 0) self.theGrid.addWidget(self.subUstdsLab, 16, 0) self.theGrid.addLayout(self.entryGridSub, 12, 1, 5, 3) self.theGrid.addWidget(self.impvLab, 19, 0) self.theGrid.addWidget(self.impvAffLab, 19, 1) self.theGrid.addWidget(self.impvNegLab, 19, 2) self.theGrid.addWidget(self.impvTu, 20, 0) self.theGrid.addWidget(self.impvUd, 21, 0) self.theGrid.addWidget(self.impvNos, 22, 0) self.theGrid.addWidget(self.impvUdes, 23, 0) self.theGrid.addLayout(self.entryGridImpv, 20, 1, 4, 2) self.theGrid.addWidget(self.checkBut, 19, 5) self.theGrid.addWidget(self.saveBut, 20, 5) self.theGrid.addWidget(self.clearBut, 21, 5) self.theGrid.addWidget(self.newBut, 22, 5) self.theGrid.addWidget(self.quitBut, 23, 5) for i in range(24): self.theGrid.setRowStretch(i, 1) for j in range(6): self.theGrid.setColumnStretch(j, 1) self.w.setLayout(self.theGrid) self.getDic() def check(self): word = self.infEntry.text().upper() if word in self.wordList: msgBox = QMessageBox() msgBox.setText(word + ' already in dictionary') msgBox.exec_() else: msgBox = QMessageBox() msgBox.setText(word + ' not in dictionary yet') msgBox.exec_() def save(self): infinitive = self.infEntry.text().upper() if infinitive in self.wordList: msgBox = QMessageBox() msgBox.setText(infinitive + ' already in dictionary') msgBox.exec_() else: self.wordList.append(infinitive) indList = [] subList = [] impList = [] for i in range(self.entryGridInd.count()): item = self.entryGridInd.itemAt(i) child = item.widget() indList.append(child.text().upper()) for i in range(self.entryGridSub.count()): item = self.entryGridSub.itemAt(i) child = item.widget() subList.append(child.text().upper()) for i in range(self.entryGridImpv.count()): item = self.entryGridImpv.itemAt(i) child = item.widget() impList.append(child.text().upper()) self.newDic['INF'] = infinitive self.newDic['IND'] = indList self.newDic['SUB'] = subList self.newDic['IMP'] = impList self.conjDicList.append(self.newDic) c = open('conj.txt', 'w') json.dump(self.conjDicList, c) c.close() msgBox = QMessageBox() msgBox.setText(infinitive + ' has been saved') msgBox.exec_() self.newDic = {'INF': '', 'IND': '', 'SUB': '', 'IMP': ''} def new(self): confirm = QMessageBox.question( self.w, 'New Word', 'Are you sure you want to clear all entries \nand start a new word?', QMessageBox.Yes | QMessageBox.No) if confirm == QMessageBox.Yes: self.infEntry.clear() for i in range(self.entryGridInd.count()): item = self.entryGridInd.itemAt(i) child = item.widget() child.clear() for i in range(self.entryGridSub.count()): item = self.entryGridSub.itemAt(i) child = item.widget() child.clear() for i in range(self.entryGridImpv.count()): item = self.entryGridImpv.itemAt(i) child = item.widget() child.clear() else: pass def clear(self): confirm = QMessageBox.question( self.w, 'Clear', 'Are you sure you want to clear all entries?', QMessageBox.Yes | QMessageBox.No) if confirm == QMessageBox.Yes: self.infEntry.clear() for i in range(self.entryGridInd.count()): item = self.entryGridInd.itemAt(i) child = item.widget() child.clear() for i in range(self.entryGridSub.count()): item = self.entryGridSub.itemAt(i) child = item.widget() child.clear() for i in range(self.entryGridImpv.count()): item = self.entryGridImpv.itemAt(i) child = item.widget() child.clear() else: pass def quit(self): confirm = QMessageBox.question(self.w, 'Quit', 'Are you sure you want to exit?', QMessageBox.Yes | QMessageBox.No) if confirm == QMessageBox.Yes: self.close() else: pass def getDic(self): try: c = open('conj.txt', 'r') self.conjDicList = json.load(c) c.close() for item in self.conjDicList: self.wordList.append(item['INF']) except: self.conjDicList = []
def __init__(self, pathtoebook, book_id=None, from_calibre=False, dsettings={}, calibre_libpaths=[], parent=None): QDialog.__init__(self, parent=parent) self.gui = parent self.pathtoebook = pathtoebook self.book_id = book_id self.from_calibre = from_calibre self.calibre_libpaths = calibre_libpaths self.dsettings = MR_SETTINGS.copy() self.dsettings.update(dsettings) self.ebook = None self.eborig = None self.cleanup_dirs = [] self.cleanup_files = [] self.log = [] self.rename_file_map = {} self.meta, self.errors = {}, {} self.is_scrambled = False self.dummyimg = None self.dummysvg = '' self.setWindowTitle(CAPTION) self.setWindowIcon(get_icons('images/plugin_icon.png')) # create widgets self.buttonBox = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel) self.buttonBox.button( QDialogButtonBox.Save).setText('Save scrambled ebook && Exit') self.browser = QTextBrowser() self.browser.setText('') self.browser.setLineWrapMode(QTextBrowser.NoWrap) self.browser.setMinimumWidth(600) self.browser.setMinimumHeight(150) self.browser.setReadOnly(True) self.savefile = QLineEdit() self.savefile.setReadOnly(True) self.sourcefile = QLineEdit() self.sourcefile.setMinimumWidth(100) self.sourcefile.setReadOnly(True) self.browsesource = QPushButton('...') self.browsesource.setMaximumWidth(30) about_button = QPushButton('About', self) self.runButton = QPushButton('Scramble now') previewButton = QPushButton('Preview content') if Webview is None: previewButton.setEnabled(False) previewButton.setToolTip( 'Preview not currently available for this book') configButton = QPushButton('Change rules *') configButton.setToolTip( 'Only available in standalone version, not calibre plugin') metadataButton = QPushButton('View metadata *') metadataButton.setToolTip( 'Only available in standalone version, not calibre plugin') errorsButton = QPushButton('View errors *') errorsButton.setToolTip( 'Only available in standalone version, not calibre plugin') # layout widgets gpsource = QGroupBox('Source ebook:') laysource = QGridLayout() gpsource.setLayout(laysource) laysource.addWidget(self.sourcefile, 0, 0) laysource.addWidget(self.browsesource, 0, 1) gptarget = QGroupBox('Scrambled ebook:') laytarget = QGridLayout() gptarget.setLayout(laytarget) laytarget.addWidget(self.savefile, 0, 0) gpaction = QGroupBox('Actions:') layaction = QVBoxLayout() gpaction.setLayout(layaction) layaction.addWidget(self.runButton) layaction.addStretch() layaction.addWidget(previewButton) layaction.addStretch() gpextras = QGroupBox('Extras:') layaction2 = QVBoxLayout() gpextras.setLayout(layaction2) layaction2.addWidget(configButton) layaction2.addWidget(metadataButton) layaction2.addWidget(errorsButton) layaction3 = QVBoxLayout() layaction3.addWidget(about_button) layaction3.addStretch() layaction3.addWidget(gpextras) grid = QGridLayout() grid.addWidget(self.browser, 0, 0) grid.addLayout(layaction3, 0, 1) grid.addWidget(gpsource, 2, 0) grid.addWidget(gptarget, 3, 0) grid.addWidget(gpaction, 2, 1, 2, 1) grid.addWidget(self.buttonBox, 5, 0, 1, 2) self.setLayout(grid) # create connect signals/slots about_button.clicked.connect(self.about_button_clicked) self.runButton.clicked.connect(self.create_scramble_book) previewButton.clicked.connect(self.preview_ebook) configButton.clicked.connect(self.change_rules) metadataButton.clicked.connect(self.view_metadata) errorsButton.clicked.connect(self.view_errors) self.browsesource.clicked.connect(self.choose_source_ebook) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) if self.from_calibre: gpextras.setVisible( False) # Extras not available in calibre plugin self.browsesource.setVisible( False) # ebook file selection done by calibre self.initialise_new_file(self.pathtoebook)
def __init__(self, parent = None): super(MainWidget, self).__init__(parent) # member variables self._lTheorySpd = 0 self._rTheorySpd = 0 self._serialSend = SerialSend() # mainWindow properties self.setObjectName('MainWidget') self.setWindowIcon(QIcon(':/image/default/app.icon')) self.setWindowTitle('%s V%s' % ( qApp.applicationDisplayName(), qApp.applicationVersion())) self.resize(800, 480) # mainWindow layout # top self.groupBoxTop = QGroupBox(self) self.groupBoxTop.setObjectName('groupBoxTop') # command dashboard buttonLeftPower = JSwitchButton(parent = self.groupBoxTop) buttonRightPower = JSwitchButton(parent = self.groupBoxTop) buttonSettings = QPushButton(self.groupBoxTop) buttonHistory = QPushButton(self.groupBoxTop) buttonQuit = QPushButton(self.groupBoxTop) buttonLeftPower.setObjectName('buttonLeftPower') buttonRightPower.setObjectName('buttonRightPower') buttonSettings.setObjectName('buttonSettings') buttonHistory.setObjectName('buttonHistory') buttonQuit.setObjectName('buttonQuit') areaPortState = QWidget(self) areaPortState.setObjectName('areaPortState') areaPortState.setStyleSheet('QWidget#areaPortState{border-radius:3px;' 'border:1px solid #505050;' 'background-color:rgba(64,64,64,50);}') vertLayoutPortState = QVBoxLayout(areaPortState) vertLayoutPortState.setContentsMargins(50, 2, 50, 2) vertLayoutPortState.setSpacing(3) buttonPortState = JSwitchButton(pixmap = QPixmap(':/carmonitor/image/button-port-state.png'), parent = areaPortState) buttonPortState.setObjectName('buttonPortState') vertLayoutPortState.addWidget(QLabel('串口', areaPortState), 0, Qt.AlignHCenter) vertLayoutPortState.addWidget(buttonPortState) # horiLayoutTop = QHBoxLayout(self.groupBoxTop) horiLayoutTop.setContentsMargins(0, 0, 0, 0) horiLayoutTop.addSpacing(25) horiLayoutTop.addWidget(buttonSettings, 0, Qt.AlignLeft) horiLayoutTop.addSpacing(20) horiLayoutTop.addWidget(buttonHistory, 0, Qt.AlignLeft) horiLayoutTop.addSpacing(65) horiLayoutTop.addWidget(buttonLeftPower) horiLayoutTop.addWidget(QLabel('左电源开关', self.groupBoxTop)) horiLayoutTop.addStretch() horiLayoutTop.addWidget(areaPortState, 0, Qt.AlignTop) horiLayoutTop.addStretch() horiLayoutTop.addWidget(QLabel('右电源开关', self.groupBoxTop)) horiLayoutTop.addWidget(buttonRightPower) horiLayoutTop.addSpacing(150) horiLayoutTop.addWidget(buttonQuit, 0, Qt.AlignRight) horiLayoutTop.addSpacing(25) # middle # curves self.curveLBP = CurveWidget(title = '左刹车压力(MPa)', parent = self) self.curveLRP = CurveWidget(title = '左转速(r/min)', parent = self) self.curveRBP = CurveWidget(title = '右刹车压力(MPa)', parent = self) self.curveRRP = CurveWidget(title = '右转速(r/min)', parent = self) self.curveLBP.setObjectName('curveLBP') self.curveLRP.setObjectName('curveLRP') self.curveRBP.setObjectName('curveRBP') self.curveRRP.setObjectName('curveRRP') # self.curveLBP.setAxisScale(QwtPlot.yLeft, 0, 30, 5) # areaMiddle self.areaMiddle = QWidget(self) self.areaMiddle.setObjectName('areaMiddle') self.areaMiddle.setFixedWidth(280) # groupBoxStatus = QGroupBox(self) groupBoxStatus.setObjectName('groupBoxStatus') # status-view gridLayoutStatus = QGridLayout(groupBoxStatus) gridLayoutStatus.setContentsMargins(5, 5, 5, 5) gridLayoutStatus.setHorizontalSpacing(8) gridLayoutStatus.setVerticalSpacing(3) # Brake-Command editLeftBrakeCmd = QLineEdit(groupBoxStatus) editRightBrakeCmd = QLineEdit(groupBoxStatus) editLeftBrakeCmd.setObjectName('editLeftBrakeCmd') editRightBrakeCmd.setObjectName('editRightBrakeCmd') editLeftBrakeCmd.setReadOnly(True) editRightBrakeCmd.setReadOnly(True) gridLayoutStatus.addWidget(QLabel('刹车指令:', groupBoxStatus), 0, 0, 1, 2, Qt.AlignCenter) gridLayoutStatus.addWidget(editLeftBrakeCmd, 1, 0, 1, 1) gridLayoutStatus.addWidget(editRightBrakeCmd, 1, 1, 1, 1) # Major Brake Pressure self.editMLeftBrakeP = QLineEdit(groupBoxStatus) self.editMRightBrakeP = QLineEdit(groupBoxStatus) self.editMLeftBrakeP.setObjectName('editMLeftBrakeP') self.editMRightBrakeP.setObjectName('editMRightBrakeP') self.editMLeftBrakeP.setReadOnly(True) self.editMRightBrakeP.setReadOnly(True) gridLayoutStatus.addWidget(QLabel('主刹车压力:', groupBoxStatus), 2, 0, 1, 2, Qt.AlignCenter) gridLayoutStatus.addWidget(self.editMLeftBrakeP, 3, 0, 1, 1) gridLayoutStatus.addWidget(self.editMRightBrakeP, 3, 1, 1, 1) # Assistant Brake Pressure self.editALeftBrakeP = QLineEdit(groupBoxStatus) self.editARightBrakeP = QLineEdit(groupBoxStatus) self.editALeftBrakeP.setObjectName('editALeftBrakeP') self.editARightBrakeP.setObjectName('editARightBrakeP') self.editALeftBrakeP.setReadOnly(True) self.editARightBrakeP.setReadOnly(True) gridLayoutStatus.addWidget(QLabel('副刹车压力:', groupBoxStatus), 4, 0, 1, 2, Qt.AlignCenter) gridLayoutStatus.addWidget(self.editALeftBrakeP, 5, 0, 1, 1) gridLayoutStatus.addWidget(self.editARightBrakeP, 5, 1, 1, 1) # Rotation Rate self.editLeftRotateRate = QLineEdit(groupBoxStatus) self.editRightRotateRate = QLineEdit(groupBoxStatus) self.editLeftRotateRate.setObjectName('editLeftRotateRate') self.editRightRotateRate.setObjectName('editRightRotateRate') gridLayoutStatus.addWidget(QLabel('实际转速:', groupBoxStatus), 6, 0, 1, 2, Qt.AlignCenter) gridLayoutStatus.addWidget(self.editLeftRotateRate, 7, 0, 1, 1) gridLayoutStatus.addWidget(self.editRightRotateRate, 7, 1, 1, 1) # Theory Rotation Rate self.editTheoryLeftRotateRate = QLineEdit(groupBoxStatus) self.editTheoryRightRotateRate = QLineEdit(groupBoxStatus) self.editTheoryLeftRotateRate.setObjectName('editTheoryLeftRotateRate') self.editTheoryRightRotateRate.setObjectName('editTheoryRightRotateRate') gridLayoutStatus.addWidget(QLabel('理论转速:', groupBoxStatus), 8, 0, 1, 2, Qt.AlignCenter) gridLayoutStatus.addWidget(self.editTheoryLeftRotateRate, 9, 0, 1, 1) gridLayoutStatus.addWidget(self.editTheoryRightRotateRate, 9, 1, 1, 1) # groupBoxCtrl = QGroupBox(self) groupBoxCtrl.setObjectName('groupBoxCtrl') # status-view gridLayoutCtrl = QGridLayout(groupBoxCtrl) gridLayoutCtrl.setContentsMargins(5, 5, 5, 5) gridLayoutCtrl.setSpacing(20) # left-button buttonLeftDashboard = JDashButton('左指令旋钮', groupBoxCtrl) buttonLeftSpeedGain = JDashButton('左转速增益', groupBoxCtrl) buttonLeftSpeedKnob = JDashButton('左转速增益', groupBoxCtrl) buttonLeftTracksip = JTracksipButton(parent = groupBoxCtrl) buttonLeftDashboard.setObjectName('buttonLeftDashboard') buttonLeftSpeedGain.setObjectName('buttonLeftSpeedGain') buttonLeftSpeedKnob.setObjectName('buttonLeftSpeedKnob') buttonLeftTracksip.setObjectName('buttonLeftTracksip') buttonLeftTracksip.setFixedSize(110, 45) # right-button buttonRightDashboard = JDashButton('右指令旋钮', groupBoxCtrl) buttonRightSpeedGain = JDashButton('右转速增益', groupBoxCtrl) buttonRightSpeedKnob = JDashButton('右转速增益', groupBoxCtrl) buttonRightTracksip = JTracksipButton(parent = groupBoxCtrl) buttonRightDashboard.setObjectName('buttonRightDashboard') buttonRightSpeedGain.setObjectName('buttonRightSpeedGain') buttonRightSpeedKnob.setObjectName('buttonRightSpeedKnob') buttonRightTracksip.setObjectName('buttonRightTracksip') buttonRightTracksip.setFixedSize(110, 45) horiLayoutTracksip = QHBoxLayout() horiLayoutTracksip.setContentsMargins(0, 0, 0, 0) horiLayoutTracksip.setSpacing(5) horiLayoutTracksip.addWidget(buttonLeftTracksip) horiLayoutTracksip.addWidget(QLabel('打滑', self), 0, Qt.AlignHCenter) horiLayoutTracksip.addWidget(buttonRightTracksip) gridLayoutCtrl.addLayout(horiLayoutTracksip, 0, 0, 1, 2) horiLayoutDashboard = QHBoxLayout() horiLayoutDashboard.setContentsMargins(0, 0, 0, 0) horiLayoutDashboard.setSpacing(5) horiLayoutDashboard.addWidget(buttonLeftDashboard) horiLayoutDashboard.addWidget(QLabel(' ', self), 0, Qt.AlignHCenter) horiLayoutDashboard.addWidget(buttonRightDashboard) gridLayoutCtrl.addLayout(horiLayoutDashboard, 1, 0, 1, 2) horiLayoutSpeedGain = QHBoxLayout() horiLayoutSpeedGain.setContentsMargins(0, 0, 0, 0) horiLayoutSpeedGain.setSpacing(5) horiLayoutSpeedGain.addWidget(buttonLeftSpeedGain) horiLayoutSpeedGain.addWidget(QLabel('(粗调)', self), 0, Qt.AlignHCenter) horiLayoutSpeedGain.addWidget(buttonRightSpeedGain) gridLayoutCtrl.addLayout(horiLayoutSpeedGain, 2, 0, 1, 2) horiLayoutSpeedKnob = QHBoxLayout() horiLayoutSpeedKnob.setContentsMargins(0, 0, 0, 0) horiLayoutSpeedKnob.setSpacing(5) horiLayoutSpeedKnob.addWidget(buttonLeftSpeedKnob) horiLayoutSpeedKnob.addWidget(QLabel('(细调)', self), 0, Qt.AlignHCenter) horiLayoutSpeedKnob.addWidget(buttonRightSpeedKnob) gridLayoutCtrl.addLayout(horiLayoutSpeedKnob, 3, 0, 1, 2) # vertLayoutMid = QVBoxLayout(self.areaMiddle) vertLayoutMid.setContentsMargins(0, 0, 0, 0) vertLayoutMid.setSpacing(0) vertLayoutMid.addWidget(groupBoxStatus) vertLayoutMid.addWidget(groupBoxCtrl) vertLayoutMid.addSpacing(20) # gridLayoutBottom = QGridLayout() gridLayoutBottom.setContentsMargins(0, 0, 0, 0) gridLayoutBottom.setSpacing(1) gridLayoutBottom.addWidget(self.curveLBP, 0, 0, 1, 1) gridLayoutBottom.addWidget(self.curveLRP, 1, 0, 1, 1) gridLayoutBottom.addWidget(self.areaMiddle, 0, 1, 2, 1) gridLayoutBottom.addWidget(self.curveRBP, 0, 2, 1, 1) gridLayoutBottom.addWidget(self.curveRRP, 1, 2, 1, 1) # main-layout vertLayoutMain = QVBoxLayout(self) vertLayoutMain.setContentsMargins(5, 5, 5, 5) vertLayoutMain.addWidget(self.groupBoxTop) vertLayoutMain.addLayout(gridLayoutBottom) # global properties qApp.setProperty('MainWidget', self) self._serialProxy = SerialPortProxy(self) self._serialProxy._serialSimulate = SerialSimulate(self._serialProxy) # qApp.setProperty('SerialProxy', self._serialProxy) # buttonSettings.clicked.connect(self.onButtonSettingsClicked) buttonHistory.clicked.connect(self.onButtonHistoryClicked) buttonPortState.clicked.connect(self.onButtonPortStateClicked) buttonQuit.clicked.connect(self.onButtonQuitClicked) # curves self.curveLBP.doubleClicked.connect(self.onCurveDoubleClicked) self.curveLRP.doubleClicked.connect(self.onCurveDoubleClicked) self.curveRBP.doubleClicked.connect(self.onCurveDoubleClicked) self.curveRRP.doubleClicked.connect(self.onCurveDoubleClicked) # switch-power buttonLeftPower.stateChanged.connect(self.onButtonLeftPowerStateChanged) buttonRightPower.stateChanged.connect(self.onButtonRightPowerStateChanged) # switch-tracksip buttonLeftTracksip.stateChanged.connect(self.onButtonLeftTracksipStateChanged) buttonRightTracksip.stateChanged.connect(self.onButtonRightTracksipStateChanged) self._serialProxy.stateChanged.connect(self.onSerialStateChanged) self._serialProxy.serialPortError.connect(self.onSerialPortError) self._serialProxy.displayRespond.connect(self.onSerialDisplayRespond) # buttonLeftSpeedGain.clicked.connect(self.execSliderWidget) buttonLeftSpeedKnob.clicked.connect(self.execSliderWidget) buttonRightSpeedGain.clicked.connect(self.execSliderWidget) buttonRightSpeedKnob.clicked.connect(self.execSliderWidget) # final initialization self.editMLeftBrakeP.setText('0 MPa') self.editMRightBrakeP.setText('0 MPa') self.editALeftBrakeP.setText('0 MPa') self.editARightBrakeP.setText('0 MPa') self.editLeftRotateRate.setText('0 r/min') self.editRightRotateRate.setText('0 r/min') self.editTheoryLeftRotateRate.setText('0 r/min') self.editTheoryRightRotateRate.setText('0 r/min') # c_memset(self._serialSend, 0, ctypes.sizeof(self._serialSend)) # SQL sqlName = applicationDirPath() \ + '/../data/cm-' \ + QDateTime.currentDateTime().toLocalTime().toString('yyyy-MM-dd-HH-mm-ss') \ + '.db' if not DatabaseMgr().create(sqlName): assert(False) # start serialport self._serialProxy.start() # buttonLeftTracksip.setState(self._serialSend.ctrlWord.lTracksip) buttonRightTracksip.setState(self._serialSend.ctrlWord.lTracksip)