def choices_widget(self, name, choices, fallback_val, none_val, prefs=None): prefs = prefs or tprefs widget = QComboBox(self) widget.currentIndexChanged[int].connect(self.emit_changed) for key, human in sorted( choices.iteritems(), key=lambda key_human: key_human[1] or key_human[0]): widget.addItem(human or key, key) def getter(w): ans = unicode(w.itemData(w.currentIndex()) or '') return {none_val: None}.get(ans, ans) def setter(w, val): val = {None: none_val}.get(val, val) idx = w.findData(val, flags=Qt.MatchFixedString | Qt.MatchCaseSensitive) if idx == -1: idx = w.findData(fallback_val, flags=Qt.MatchFixedString | Qt.MatchCaseSensitive) w.setCurrentIndex(idx) return self(name, widget=widget, getter=getter, setter=setter, prefs=prefs)
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 build_control_bar(self): # Add control bar control_row_layout = QHBoxLayout(self) control_row_layout.setContentsMargins(0, 0, 0, 0) # DB type combo box db_combo_box = QComboBox(self) for dbname in UI.CONNECTION_STRING_SUPPORTED_DB_NAMES: db_combo_box.addItem(dbname) control_row_layout.addWidget(db_combo_box) # Connection string self.connection_line = QLineEdit(self) self.connection_line.setPlaceholderText( UI.CONNECTION_STRING_PLACEHOLDER) self.connection_line.setText(UI.CONNECTION_STRING_DEFAULT) control_row_layout.addWidget(self.connection_line) # Connection button connection_button = QPushButton(self) connection_button.setText(UI.QUERY_CONTROL_CONNECT_BUTTON_TEXT) connection_button.clicked.connect(self.on_connect_click) control_row_layout.addWidget(connection_button) # Add contol row as a first widget in a column control_row = QWidget(self) control_row.setLayout(control_row_layout) return control_row
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.label = QLabel("Voice") self.l.addWidget(self.label) self.voiceOptions = QComboBox() self.l.addWidget(self.voiceOptions) self.rateLabel = QLabel("Rate (-10 to 10)") self.l.addWidget(self.rateLabel) self.rateEdit = QLineEdit() self.rateEdit.setValidator(QIntValidator(-10, 10)) self.rateEdit.setText(str(prefs['rate'])) self.l.addWidget(self.rateEdit) self.volumeLabel = QLabel("Volume (0 to 100)") self.volumeEdit = QLineEdit() self.volumeEdit.setValidator(QIntValidator(0, 100)) self.volumeEdit.setText(str(prefs['volume'])) self.l.addWidget(self.volumeLabel) self.l.addWidget(self.volumeEdit) import win32com.client self.spVoice = win32com.client.Dispatch("SAPI.SpVoice") voices = self.spVoice.GetVoices("", "") for i in range(voices.Count): self.voiceOptions.addItem(voices.Item(i).GetDescription()) if voices.Item(i).GetDescription() == prefs['voice']: self.voiceOptions.setCurrentIndex(i) self.pauseHotKey = HotkeyWidget(prefs, "pause", "Enable Pause/Play hotkey") self.l.addWidget(self.pauseHotKey) self.stopHotKey = HotkeyWidget(prefs, "stop", "Enable Stop hotkey") self.l.addWidget(self.stopHotKey) self.selectHotKey = HotkeyWidget(prefs, "select", "Enable Select Mode hotkey") self.l.addWidget(self.selectHotKey) def save_settings(self): from calibre_plugins.tts_ebook_viewer.hotkeys import keycodes prefs['voice'] = unicode(self.voiceOptions.currentText()) prefs['rate'] = int(self.rateEdit.text()) prefs['volume'] = int(self.volumeEdit.text()) self.pauseHotKey.save_settings(prefs) self.stopHotKey.save_settings(prefs) self.selectHotKey.save_settings(prefs)
def make_color_combobox(self, row, dex): c = QComboBox(self) c.addItem('') c.addItems(QColor.colorNames()) self.table.setCellWidget(row, 1, c) if dex >= 0: c.setCurrentIndex(dex) return c
class ConfigWidget(QWidget): def __init__(self): super().__init__() vl = QVBoxLayout() self.setLayout(vl) self.search_people_box = QCheckBox('Search people') self.search_people_box.setChecked(prefs['search_people']) vl.addWidget(self.search_people_box) model_size_hl = QHBoxLayout() model_size_label = QLabel('spaCy model size') self.model_size_box = QComboBox() for size in ['sm', 'md', 'lg']: self.model_size_box.addItem(size) self.model_size_box.setCurrentText(prefs['model_size']) model_size_hl.addWidget(model_size_label) model_size_hl.addWidget(self.model_size_box) vl.addLayout(model_size_hl) zh_wiki_hl = QHBoxLayout() zh_label = QLabel('Chinese Wikipedia variant') self.zh_wiki_box = QComboBox() zh_variants = { 'cn': '大陆简体', 'hk': '香港繁體', 'mo': '澳門繁體', 'my': '大马简体', 'sg': '新加坡简体', 'tw': '臺灣正體' } for variant, text in zh_variants.items(): self.zh_wiki_box.addItem(text, variant) self.zh_wiki_box.setCurrentText(zh_variants[prefs['zh_wiki_variant']]) zh_wiki_hl.addWidget(zh_label) zh_wiki_hl.addWidget(self.zh_wiki_box) vl.addLayout(zh_wiki_hl) donate_button = QPushButton('Donate') donate_button.clicked.connect(self.donate) vl.addWidget(donate_button) github_button = QPushButton('Source code') github_button.clicked.connect(self.github) vl.addWidget(github_button) @staticmethod def donate(): webbrowser.open('https://liberapay.com/xxyzz/donate') def github(self): webbrowser.open('https://github.com/xxyzz/WordDumb') def save_settings(self): prefs['search_people'] = self.search_people_box.isChecked() prefs['model_size'] = self.model_size_box.currentText() prefs['zh_wiki_variant'] = self.zh_wiki_box.currentData()
def __init__(self, parent_dialog, plugin_action): self.parent_dialog = parent_dialog self.plugin_action = plugin_action QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) label = QLabel(_("If you have custom columns defined, they will be listed below. Choose how you would like these columns handled.")) label.setWordWrap(True) self.l.addWidget(label) self.l.addSpacing(5) scrollable = QScrollArea() scrollcontent = QWidget() scrollable.setWidget(scrollcontent) scrollable.setWidgetResizable(True) self.l.addWidget(scrollable) self.sl = QVBoxLayout() scrollcontent.setLayout(self.sl) self.custcol_dropdowns = {} custom_columns = self.plugin_action.gui.library_view.model().custom_columns grid = QGridLayout() self.sl.addLayout(grid) row=0 for key, column in custom_columns.iteritems(): if column['datatype'] in permitted_values: # logger.debug("\n============== %s ===========\n"%key) # for (k,v) in column.iteritems(): # logger.debug("column['%s'] => %s"%(k,v)) label = QLabel('%s(%s)'%(column['name'],key)) label.setToolTip(_("Set this %s column on new merged books...")%column['datatype']) grid.addWidget(label,row,0) dropdown = QComboBox(self) dropdown.addItem('','none') for md in permitted_values[column['datatype']]: # tags-like column also 'text' if md == 'union' and not column['is_multiple']: continue if md == 'concat' and column['is_multiple']: continue dropdown.addItem(titleLabels[md],md) self.custcol_dropdowns[key] = dropdown if key in prefs['custom_cols']: dropdown.setCurrentIndex(dropdown.findData(prefs['custom_cols'][key])) dropdown.setToolTip(_("How this column will be populated by default.")) grid.addWidget(dropdown,row,1) row+=1 self.sl.insertStretch(-1)
def __init__(self, parent_dialog, plugin_action): self.parent_dialog = parent_dialog self.plugin_action = plugin_action QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) label = QLabel(_("If you have custom columns defined, they will be listed below. Choose how you would like these columns handled.")) label.setWordWrap(True) self.l.addWidget(label) self.l.addSpacing(5) scrollable = QScrollArea() scrollcontent = QWidget() scrollable.setWidget(scrollcontent) scrollable.setWidgetResizable(True) self.l.addWidget(scrollable) self.sl = QVBoxLayout() scrollcontent.setLayout(self.sl) self.custcol_dropdowns = {} custom_columns = self.plugin_action.gui.library_view.model().custom_columns grid = QGridLayout() self.sl.addLayout(grid) row=0 for key, column in custom_columns.iteritems(): if column['datatype'] in permitted_values: # print("\n============== %s ===========\n"%key) # for (k,v) in column.iteritems(): # print("column['%s'] => %s"%(k,v)) label = QLabel('%s(%s)'%(column['name'],key)) label.setToolTip(_("Set this %s column on new merged books...")%column['datatype']) grid.addWidget(label,row,0) dropdown = QComboBox(self) dropdown.addItem('','none') for md in permitted_values[column['datatype']]: # tags-like column also 'text' if md == 'union' and not column['is_multiple']: continue if md == 'concat' and column['is_multiple']: continue dropdown.addItem(titleLabels[md],md) self.custcol_dropdowns[key] = dropdown if key in prefs['custom_cols']: dropdown.setCurrentIndex(dropdown.findData(prefs['custom_cols'][key])) dropdown.setToolTip(_("How this column will be populated by default.")) grid.addWidget(dropdown,row,1) row+=1 self.sl.insertStretch(-1)
def initConvertPage(self): f = QFrame() l = QGridLayout() f.setLayout(l) row = 0 l.addWidget(QLabel('Converter :'), row, 0) currentPluginBox = QComboBox() currentPluginBox.currentTextChanged.connect(self.selectPlugin) l.addWidget(currentPluginBox, row, 1) for key in self.plugins.keys(): currentPluginBox.addItem(key) row += 1 l.addWidget(QLabel('Destination path :'), row, 0) self.destPathLbl = QLabel( self.joinSavePath(self.config[PATHS]['save_path'], self.config[FILES]['save_file'], self.config[FILES]['save_ext'])) self.destPathLbl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) l.addWidget(self.destPathLbl, row, 1) row += 1 f2 = QFrame() l2 = QHBoxLayout() f2.setLayout(l2) f3 = QFrame() l3 = QGridLayout() f3.setLayout(l3) l3.addWidget(QLabel('Destination Files :'), 0, 0) self.destFilesList = QListWidget() self.destFilesList.setAlternatingRowColors(True) l3.addWidget(self.destFilesList, 1, 0) l2.addWidget(self.initFileFrame()) l2.addWidget(f3) l.addWidget(f2, row, 0, 1, 3) row += 1 l.addWidget(self.initSrcFiles(), row, 0, 1, 3) row += 1 self.convertBtn = QPushButton('Convert') self.convertBtn.clicked.connect(self.handleConvertClicked) self.convertBtn.setEnabled(False) l.addWidget(self.convertBtn, row, 0, 1, 3) return f
def __init__(self): super().__init__() self._layout = QVBoxLayout() host_label = QLabel("Server host (where EvilOSX will connect to):") self._host_field = QLineEdit() self._layout.addWidget(host_label) self._layout.addWidget(self._host_field) port_label = QLabel("Server port:") self._port_field = QLineEdit() self._layout.addWidget(port_label) self._layout.addWidget(self._port_field) live_label = QLabel( "Where should EvilOSX live? (Leave empty for ~/Library/Containers/.<RANDOM>): " ) self._live_field = QLineEdit() self._layout.addWidget(live_label) self._layout.addWidget(self._live_field) launcher_label = QLabel("Launcher name:") self._launcher_combobox = QComboBox() for launcher_name in launchers.get_names(): self._launcher_combobox.addItem(launcher_name) self._layout.addWidget(launcher_label) self._layout.addWidget(self._launcher_combobox) loader_label = QLabel("Loader name:") loader_combobox = QComboBox() self._loader_layout = QVBoxLayout() for loader_name in loaders.get_names(): loader_combobox.addItem(loader_name) self._layout.addWidget(loader_label) self._layout.addWidget(loader_combobox) loader_combobox.currentTextChanged.connect(self._set_on_loader_change) # Dynamically loaded loader layout self._layout.addLayout(self._loader_layout) self._set_on_loader_change(loader_combobox.currentText()) self._layout.setContentsMargins(10, 10, 10, 0) self._layout.setAlignment(Qt.AlignTop) self.setLayout(self._layout)
def ins_button_clicked(self): row = self.table.currentRow() if row < 0: error_dialog(self, _('Select a cell'), _('Select a cell before clicking the button'), show=True) return self.table.insertRow(row) self.table.setItem(row, 0, QTableWidgetItem()) c = QComboBox(self) c.addItem('') c.addItems(QColor.colorNames()) self.table.setCellWidget(row, 1, c)
def init_control_bar(self): control_row_layout = QHBoxLayout(self) control_row_layout.setContentsMargins(0, 0, 0, 0) db_combo_box = QComboBox(self) db_combo_box.addItem('SQLite') # db_combo_box.addItem('PostgreSQL') control_row_layout.addWidget(db_combo_box) self.connection_line = QLineEdit(self) self.connection_line.setPlaceholderText(DEFAULT_CONNECTION_LINE) self.connection_line.setText('') control_row_layout.addWidget(self.connection_line) connection_button = QPushButton(self) connection_button.setText('Connect') connection_button.clicked.connect(self.on_connect_click) control_row_layout.addWidget(connection_button) control_row = QWidget(self) control_row.setLayout(control_row_layout) return control_row
def choices_widget(self, name, choices, fallback_val, none_val, prefs=None): prefs = prefs or tprefs widget = QComboBox(self) widget.currentIndexChanged[int].connect(self.emit_changed) for key, human in sorted(choices.iteritems(), key=lambda key_human: key_human[1] or key_human[0]): widget.addItem(human or key, key) def getter(w): ans = unicode(w.itemData(w.currentIndex()) or '') return {none_val:None}.get(ans, ans) def setter(w, val): val = {None:none_val}.get(val, val) idx = w.findData(val, flags=Qt.MatchFixedString|Qt.MatchCaseSensitive) if idx == -1: idx = w.findData(fallback_val, flags=Qt.MatchFixedString|Qt.MatchCaseSensitive) w.setCurrentIndex(idx) return self(name, widget=widget, getter=getter, setter=setter, prefs=prefs)
def init_control_bar(self): # Add control bar control_row_layout = QHBoxLayout(self) control_row_layout.setContentsMargins(0, 0, 0, 0) # DB type combo box db_combo_box = QComboBox(self) db_combo_box.addItem('SQLite') db_combo_box.addItem('PostgreSQL') control_row_layout.addWidget(db_combo_box) # Connection string self.connection_line = QLineEdit(self) self.connection_line.setPlaceholderText('Enter...') self.connection_line.setText('demo.db') control_row_layout.addWidget(self.connection_line) # Connection button connection_button = QPushButton(self) connection_button.setText('Connect') connection_button.clicked.connect(self.on_connect_click) control_row_layout.addWidget(connection_button) # Add contol row as a first widget in a column control_row = QWidget(self) control_row.setLayout(control_row_layout) return control_row
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())
class ThemeChooser(QWidget): """docstring for ThemeChooser.""" themeChanged = pyqtSignal(str) def __init__(self, parent): super(ThemeChooser, self).__init__(parent) self.currentIconTheme = QIcon.themeName() self.label = QLabel(self) self.comboBox = QComboBox(self) self.setLayout(QVBoxLayout(self)) self.label.setText('Available themes :') self.layout().addWidget(self.label) self.layout().addWidget(self.comboBox) self.comboBox.currentTextChanged.connect(self.onThemeChanged) self.populateComboBox() def populateComboBox(self): self.comboBox.clear() for path in QIcon.themeSearchPaths(): for subdir in helpers.listing_subdir(path): if subdir.name != self.currentIconTheme: self.comboBox.addItem(subdir.name) self.comboBox.insertItem(0, self.currentIconTheme) self.comboBox.setCurrentIndex(0) def onThemeChanged(self, themeName): QIcon.setThemeName(themeName) self.themeChanged.emit(themeName) def rollback(self): self.onThemeChanged(self.currentIconTheme) def commit(self): self.currentIconTheme = QIcon.themeName()
class editpopup(QWidget): user_id = "" session = Session() def __init__(self): super().__init__() self.title = "Edit Pop Up" self.width = 500 self.height = 500 self.top = 100 self.left = 100 self.initUI() def initUI(self): self.username = QLineEdit(self) self.username.move(200, 200) self.password = QLineEdit(self) self.password.move(200, 240) self.password.setEchoMode(QLineEdit.Password) self.role = QComboBox(self) self.role.addItem("Student") self.role.addItem("Librarian") self.role.addItem("Admin") self.role.move(200, 280) self.savechanges = QPushButton("Save changes", self) self.savechanges.move(250, 350) self.savechanges.clicked.connect(self.updateValues) self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) def setValues(self, user_id, user_name, user_password, user_role): self.user_id = user_id self.username.setText(user_name) self.password.setText(user_password) self.role.setCurrentText(user_role) def updateValues(self): result = self.session.query(User).filter( User.id == self.user_id).first() result.username = self.username.text() result.password = self.password.text() result.role = self.role.currentText() try: self.session.add(result) self.session.commit() self.close() except: print("Error occured while saving")
class AddUserUI(QMainWindow): def __init__(self): super().__init__() self.width = 640 self.height = 400 self.top = 100 self.left = 100 self.initUI() def initUI(self): self.labelUsername = QLabel(self) self.labelUsername.setText("Username") self.labelPassword = QLabel(self) self.labelPassword.setText("Password") self.labelRole = QLabel(self) self.labelRole.setText("Role") self.labelUsername.move(250, 100) self.labelPassword.move(250, 130) self.labelRole.move(250, 160) self.username = QLineEdit(self) self.username.move(300, 100) self.password = QLineEdit(self) self.password.setEchoMode(QLineEdit.Password) self.password.move(300, 130) self.role = QComboBox(self) self.role.addItem("Student") self.role.addItem("Librarian") self.role.addItem("Admin") self.role.move(300, 160) button = QPushButton("Add User", self) button.move(300, 190) button.clicked.connect(self.add_user) self.setWindowTitle("Add Users") self.setGeometry(self.left, self.top, self.width, self.height) def add_user(self): uname = self.username.text() password = self.password.text() role = self.role.currentText() print(uname) print(password) print(role) user = User(uname, password, role) session.add(user) session.commit() self.statusBar().showMessage("User Saved Successfully")
class HistoChart (QGraphicsView): def __init__(self,parent,size=QSize(400,400)): super(HistoChart,self).__init__(parent) self.my_scene = QGraphicsScene() #self.my_scene.setSceneRect(self.sceneRect()) self.setScene(self.my_scene) #self.setBackgroundBrush(QBrush(QtCore.Qt.black, QtCore.Qt.SolidPattern)); self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.size_text_width = -1 self.margin = {'top':10,'bottom':10,'left':10,'right':10} self.initialize = False self.max_length_text = 10 self.histo_items = [] def setData (self,list_items): size = min(self.frameSize().width()/2.0,self.frameSize().height()) self.size_pie = QSize(size,size) self.data = list_items if self.initialize == False: self.c_box = QComboBox() self.c_box.addItem("warrior") self.c_box.addItem("rank") self.c_box.addItem("power") self.c_box.currentIndexChanged.connect(self.update) proxy = self.my_scene.addWidget(self.c_box) proxy.setPos(QPointF(0.0,self.margin['top'])) self.margin['top']+=self.c_box.height() self.initialize = True self.update() def update(self): i = 0 #self.my_scene.clear() for item in self.histo_items : self.my_scene.removeItem(item) self.histo_items = [] self.scene().setSceneRect(QRectF(0,0,self.frameSize().width(),self.frameSize().height())) max = -1 for value in self.data.values(): if value[self.c_box.currentText()] > max: max = value[self.c_box.currentText()] size_text_number = QGraphicsTextItem(str(max)).boundingRect().width()+10 interval= self.parent().size().height()-self.margin['top']-self.margin['bottom'] interval = interval /len(self.data) temp = "aaaaaaaaaaaaaaaaa" if len(temp)> self.max_length_text: data = temp[:self.max_length_text]+"." else : data = temp self.size_text_width = QGraphicsTextItem(data).boundingRect().width()+10 #print ('width:',self.size_text_width) horizontal_size = self.parent().size().width()- self.margin['left']- self.margin['right']-self.size_text_width- size_text_number try: ratio = horizontal_size/ max except ZeroDivisionError : ratio = 0 i = 0 for groupe,value in zip(self.data.keys(),self.data.values()) : if self.c_box.currentText() == "warrior": title_str = 'Nombre de Heros' bar_all = QGraphicsRectItem(0,self.margin['top'],value['warrior']*ratio,interval*0.8) bar_all.setPos(self.size_text_width,interval*0.2+(i*interval)) gradient = QLinearGradient(QPointF(bar_all.rect().width()/2,0),QPointF(bar_all.rect().width()/2,bar_all.rect().height()+self.margin['top'])) gradient.setColorAt(0,QColor('white')) gradient.setColorAt(1,QColor('red')) brush = QBrush(gradient) #brush.setTexture(QPixmap(":/textures/"+groupe.attribs['color'])) bar_all.setBrush(brush) self.my_scene.addItem(bar_all) self.histo_items.append(bar_all) bar_alive = QGraphicsRectItem(0,self.margin['top'],value['alive']*ratio,interval*0.8) bar_alive.setPos(self.size_text_width,interval*0.2+(i*interval)) gradient = QLinearGradient(QPointF(bar_alive.rect().width()/2,0),QPointF(bar_alive.rect().width()/2,bar_alive.rect().height()+self.margin['top'])) # gradient.setStart(QPointF(0.5,0)) # gradient.setStop(QPointF(0.5,1)) gradient.setColorAt(0,QColor('white')) gradient.setColorAt(1,QColor('green')) brush = QBrush(gradient) bar_alive.setBrush(brush) self.my_scene.addItem(bar_alive) self.histo_items.append(bar_alive) text_nb_warriors= QGraphicsTextItem(str(value['warrior'])) text_nb_warriors.setDefaultTextColor(QColor('green')) trans = QTransform().translate(bar_all.pos().x()+bar_all.rect().width()+10,interval*0.2+(i*interval)+self.margin['top']) pts = trans.map(QPointF(0,0.0)) text_nb_warriors.setPos(pts.x(),pts.y()) self.my_scene.addItem(text_nb_warriors) self.histo_items.append(text_nb_warriors) #bar ranl elif self.c_box.currentText()== "rank": title_str = "Rank Moyen" bar_rank = QGraphicsRectItem(0,self.margin['top'],value['rank']*ratio,interval*0.8) bar_rank.setPos(self.size_text_width, interval*0.2+(i*interval)) gradient = QLinearGradient(QPointF(bar_rank.rect().width()/2,0),QPointF(bar_rank.rect().width()/2,bar_rank.rect().height()+self.margin['top'])) # gradient.setStart(QPointF(0.5,0)) # gradient.setStop(QPointF(0.5,1)) gradient.setColorAt(0,QColor('white')) gradient.setColorAt(1,QColor('red')) brush = QBrush(gradient) bar_rank.setBrush(brush) self.my_scene.addItem(bar_rank) self.histo_items.append(bar_rank) # value text_rank = QGraphicsTextItem("{0:1.1f}".format(value['rank'])) text_rank.setDefaultTextColor(QColor('red')) trans = QTransform().translate(bar_rank.pos().x()+bar_rank.rect().width()+10,interval*0.2+(i*interval)+self.margin['top']) pts = trans.map(QPointF(0,0.0)) text_rank.setPos(pts.x(),pts.y()) self.my_scene.addItem(text_rank) self.histo_items.append(text_rank) else: title_str = "Puissance" bar_rank = QGraphicsRectItem(0,self.margin['top'],value['power']*ratio,interval*0.8) bar_rank.setPos(self.size_text_width, interval*0.2+(i*interval)) gradient = QLinearGradient(QPointF(bar_rank.rect().width()/2,0),QPointF(bar_rank.rect().width()/2,bar_rank.rect().height()+self.margin['top'])) # gradient.setStart(QPointF(0.5,0)) # gradient.setStop(QPointF(0.5,1)) gradient.setColorAt(0,QColor('white')) gradient.setColorAt(1,QColor('blue')) brush = QBrush(gradient) bar_rank.setBrush(brush) self.my_scene.addItem(bar_rank) self.histo_items.append(bar_rank) # value try : valeur = (value['power']/max)*100 except ZeroDivisionError : valeur = 0 text_rank = QGraphicsTextItem("{0:1.1f}".format(valeur)) text_rank.setDefaultTextColor(QColor('blue')) trans = QTransform().translate(bar_rank.pos().x()+bar_rank.rect().width()+10,interval*0.2+(i*interval)+self.margin['top']) pts = trans.map(QPointF(0,0.0)) text_rank.setPos(pts.x(),pts.y()) self.my_scene.addItem(text_rank) self.histo_items.append(text_rank) #dessin du titre title = QGraphicsTextItem(title_str) title.setPos(self.margin['left']+self.size_text_width+horizontal_size/2.0,self.c_box.pos().y()) self.my_scene.addItem(title) self.histo_items.append(title) #affichage des label colonne de gauche if len(groupe.name)> self.max_length_text: data = groupe.name[:self.max_length_text]+".." else : data = groupe.name text = QGraphicsTextItem(data) #text.setTextWidth(20) trans = QTransform().translate(self.margin['left'],interval*0.2+(i*interval)+self.margin['top']) pts = trans.map(QPointF(0,0.0)) text.setPos(pts.x(),pts.y()) self.my_scene.addItem(text) self.histo_items.append(text) i +=1 # self.fitInView(self.scene.sceneRect())
class Prime(QWidget): """ Main GUI window """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._crawler = Crawler() self._producer = Producer() self._config = get_config() self._path = get_path() self._selected_playlist_index = 0 self._crawl_button = QLabel(self) self._playlist_combo = QComboBox(self) self._build_gui() def _build_gui(self): main_layout = QVBoxLayout() main_layout.addLayout(self._build_playlist_layout()) main_layout.addLayout(self._build_button_layout()) self.setLayout(main_layout) self.setWindowTitle("FlukeBox") self.show() def _build_playlist_layout(self) -> QHBoxLayout: playlist_label = QLabel(self) playlist_label.setText("Playlist") self._playlist_combo.currentIndexChanged.connect( self._playlist_selected) self._fill_playlist_combo() playlist_layout = QHBoxLayout() playlist_layout.addWidget(playlist_label) playlist_layout.addWidget(self._playlist_combo) return playlist_layout def _fill_playlist_combo(self): self._playlist_combo.clear() for playlist in self._config["playlists"]: self._playlist_combo.addItem(playlist["name"]) def _build_button_layout(self) -> QVBoxLayout: edit_button = QLabel(self) edit_button.setText("Edit") edit_button.mousePressEvent = self._edit_clicked reload_button = QLabel(self) reload_button.setText("Reload") reload_button.mousePressEvent = self._reload_clicked crawl_text = "Crawl" if NewFileDetector().are_there_new_files(): crawl_text += "!" self._crawl_button.setText(crawl_text) self._crawl_button.mousePressEvent = self._crawl_clicked gen_button = QLabel(self) gen_button.setText("Play") gen_button.mousePressEvent = self._generate_clicked btn_layout = QHBoxLayout() btn_layout.addWidget(edit_button) btn_layout.addWidget(reload_button) btn_layout.addWidget(self._crawl_button) btn_layout.addWidget(gen_button) return btn_layout def _playlist_selected(self, i): self._selected_playlist_index = i def _edit_clicked(self, event): # pylint: disable=W0613, R0201 data_path = path.join(self._path["data_path"], self._path["config_file"]) subprocess.call(["open", data_path]) def _reload_clicked(self, event): # pylint: disable=W0613, R0201 self._config = reload_config() self._fill_playlist_combo() def _crawl_clicked(self, event): # pylint: disable=W0613, R0201 self._crawl_button.setText("...") self._crawler.crawl() self._crawl_button.setText("Crawl") def _generate_clicked(self, event): # pylint: disable=W0613 selected_playlist = self._config["playlists"][ self._selected_playlist_index]["name"] self._producer.produce_with_playlist(selected_playlist) self.close()
class CustomColumnsTab(QWidget): def __init__(self, parent_dialog, plugin_action): self.parent_dialog = parent_dialog self.plugin_action = plugin_action QWidget.__init__(self) custom_columns = self.plugin_action.gui.library_view.model().custom_columns self.l = QVBoxLayout() self.setLayout(self.l) label = QLabel(_("Save Source column:")) label.setToolTip(_("If set, the column below will be populated with the template below to record the source of the split file.")) label.setWordWrap(True) self.l.addWidget(label) horz = QHBoxLayout() self.sourcecol = QComboBox(self) self.sourcecol.setToolTip(_("Choose a column to populate with template on split.")) self.sourcecol.addItem('','none') for key, column in custom_columns.iteritems(): if column['datatype'] in ('text','comments','series'): self.sourcecol.addItem(column['name'],key) self.sourcecol.setCurrentIndex(self.sourcecol.findData(prefs['sourcecol'])) horz.addWidget(self.sourcecol) self.sourcetemplate = QLineEdit(self) self.sourcetemplate.setToolTip(_("Template from source book. Example: {title} by {authors}")) # if 'sourcetemplate' in prefs: self.sourcetemplate.setText(prefs['sourcetemplate']) # else: # self.sourcetemplate.setText("{title} by {authors}") horz.addWidget(self.sourcetemplate) self.l.addLayout(horz) self.l.addSpacing(5) label = QLabel(_("If you have custom columns defined, they will be listed below. Choose if you would like these columns copied to new split books.")) label.setWordWrap(True) self.l.addWidget(label) self.l.addSpacing(5) scrollable = QScrollArea() scrollcontent = QWidget() scrollable.setWidget(scrollcontent) scrollable.setWidgetResizable(True) self.l.addWidget(scrollable) self.sl = QVBoxLayout() scrollcontent.setLayout(self.sl) self.custcol_checkboxes = {} for key, column in custom_columns.iteritems(): # print("\n============== %s ===========\n"%key) # for (k,v) in column.iteritems(): # print("column['%s'] => %s"%(k,v)) checkbox = QCheckBox('%s(%s)'%(column['name'],key)) checkbox.setToolTip(_("Copy this %s column to new split books...")%column['datatype']) checkbox.setChecked(key in prefs['custom_cols'] and prefs['custom_cols'][key]) self.custcol_checkboxes[key] = checkbox self.sl.addWidget(checkbox) self.sl.insertStretch(-1)
class ConvertDialog(QDialog): hide_text = _('&Hide styles') show_text = _('&Show styles') prince_log = '' prince_file = '' prince_css = '' # GUI definition def __init__(self, mi, fmt, opf, oeb, icon): ''' :param mi: The book metadata :param fmt: The source format used for conversion :param opf: The path to the OPF file :param oeb: An OEB object for the unpacked book :param icon: The window icon ''' self.opf = opf self.oeb = oeb self.mi = mi # The unpacked book needs to be parsed before, to read the contents # of the prince-style file, if it exists self.parse() QDialog.__init__(self) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowTitle(_('Convert to PDF with Prince')) self.setWindowIcon(icon) self.l = QVBoxLayout() self.setLayout(self.l) self.title_label = QLabel(_('<b>Title:</b> %s') % self.mi.title) self.l.addWidget(self.title_label) self.format_label = QLabel(_('<b>Source format:</b> %s') % fmt) self.l.addWidget(self.format_label) self.add_book = QCheckBox(_('&Add PDF to the book record')) self.add_book.setToolTip(_('<qt>Add the converted PDF to the selected book record</qt>')) self.add_book.setChecked(prefs['add_book']) self.add_book.stateChanged.connect(self.set_add_book) self.l.addWidget(self.add_book) self.ll = QHBoxLayout() self.ll.setAlignment(Qt.AlignLeft) self.l.addLayout(self.ll) self.label_css = QLabel(_('&Custom style:')) self.ll.addWidget(self.label_css) self.css_list = QComboBox() self.css_list.setToolTip(_('<qt>Select one style to use. Additional styles can be created in the plugin configuration</qt>')) for key in sorted(prefs['custom_CSS_list'], key=lambda x: x.lower()): self.css_list.addItem(key, key) self.css_list.setCurrentIndex(self.css_list.findText(prefs['default_CSS'])) self.css_list.currentIndexChanged.connect(self.set_css) self.ll.addWidget(self.css_list) self.label_css.setBuddy(self.css_list) self.ll_ = QHBoxLayout() self.l.addLayout(self.ll_) self.label_args = QLabel(_('A&dditional command-line arguments:')) self.ll_.addWidget(self.label_args) self.args = QLineEdit(self) self.args.setText(prefs['custom_args_list'][prefs['default_CSS']]) self.args.setToolTip(_('<qt>Specify additional command-line arguments for the conversion</qt>')) self.ll_.addWidget(self.args) self.label_args.setBuddy(self.args) self.css = QTabWidget() self.l.addWidget(self.css) self.css1 = TextEditWithTooltip(self, expected_geometry=(80,20)) self.css1.setLineWrapMode(TextEditWithTooltip.NoWrap) self.css1.load_text(self.replace_templates(prefs['custom_CSS_list'][prefs['default_CSS']]),'css') self.css1.setToolTip(_('<qt>This stylesheet can be modified<br/>The default can be configured</qt>')) i = self.css.addTab(self.css1, _('C&ustom CSS')) self.css.setTabToolTip(i, _('<qt>Custom CSS stylesheet to be used for this conversion</qt>')) monofont = QFont('') monofont.setStyleHint(QFont.TypeWriter) if (self.prince_css): self.css2 = QPlainTextEdit() self.css2.setStyleSheet('* { font-family: monospace }') self.css2.setLineWrapMode(QPlainTextEdit.NoWrap) self.css2.setPlainText(self.prince_css) self.css2.setReadOnly(True) self.css2.setToolTip(_('<qt>This stylesheet cannot be modified</qt>')) i = self.css.addTab(self.css2, _('&Book CSS')) self.css.setTabToolTip(i, _('<qt>Book-specific CSS stylesheet included in the ebook file</qt>')) self.ll = QHBoxLayout() self.l.addLayout(self.ll) if (prefs['show_CSS']): self.toggle = QPushButton(self.hide_text, self) else: self.toggle = QPushButton(self.show_text, self) self.toggle.setToolTip(_('<qt>Show/hide the additional styles used for the conversion</qt>')) self.toggle.clicked.connect(self.toggle_tabs) self.convert = QPushButton(_('Con&vert'), self) self.convert.setToolTip(_('<qt>Run the conversion with Prince</qt>')) self.convert.setDefault(True) self.buttons = QDialogButtonBox(QDialogButtonBox.Cancel) self.buttons.addButton(self.toggle, QDialogButtonBox.ResetRole) self.buttons.addButton(self.convert, QDialogButtonBox.AcceptRole) self.l.addWidget(self.buttons) self.buttons.accepted.connect(self.prince_convert) self.buttons.rejected.connect(self.reject) if (not prefs['show_CSS']): self.css.hide() self.adjustSize() def toggle_tabs(self): ''' Enable/disable the CSS tabs, and store the setting ''' if (self.css.isVisible()): self.css.hide() self.label_args.hide() self.args.hide() self.toggle.setText(self.show_text) self.adjustSize() else: self.css.show() self.label_args.show() self.args.show() self.toggle.setText(self.hide_text) self.adjustSize() prefs['show_CSS'] = self.css.isVisible() def set_add_book(self): ''' Save the status of the add_book checkbox ''' prefs['add_book'] = self.add_book.isChecked() def set_css(self): ''' Fill the custom CSS text box with the selected stylesheet (and command-line arguments) ''' style = unicode(self.css_list.currentText()) self.css1.load_text(self.replace_templates(prefs['custom_CSS_list'][style]),'css') self.args.setText(prefs['custom_args_list'][style]) prefs['default_CSS'] = style def parse(self): ''' Parse the unpacked OPF file to find and read the prince-style file ''' from calibre.constants import DEBUG from os.path import dirname, join from lxml import etree import codecs if DEBUG: print(_('Parsing book...')) opf_dir = dirname(self.opf) root = etree.parse(self.opf).getroot() metadata = root.find('{*}metadata') for meta in metadata.findall("{*}meta[@name='prince-style']"): prince_id = meta.get('content') for item in self.oeb.manifest: if (item.id == prince_id): self.prince_file = item.href break if (self.prince_file): fl = codecs.open(join(opf_dir, self.prince_file), 'rb', 'utf-8') self.prince_css = fl.read() fl.close() def replace_templates(self, text): ''' Replace templates (enclosed by '@{@', '@}@') in the input text ''' import re import json from calibre.ebooks.metadata.book.formatter import SafeFormat from calibre.constants import DEBUG matches = list(re.finditer('@{@(.+?)@}@',text,re.DOTALL)) results = {} for match in reversed(matches): result = SafeFormat().safe_format(match.group(1), self.mi, ('EXCEPTION: '), self.mi) # Escape quotes, backslashes and newlines result = re.sub(r'''['"\\]''', r'\\\g<0>', result) result = re.sub('\n', r'\A ', result) results[match.group(1)] = result text = text[:match.start(0)] + result + text[match.end(0):] if DEBUG: print(_('Replacing templates')) for match in matches: print(_('Found: %s (%d-%d)') % (match.group(1), match.start(0), match.end(0))) print(_('Replace with: %s') % results[match.group(1)]) return text def prince_convert(self): ''' Call the actual Prince command to convert to PDF ''' from os import makedirs from os.path import dirname, join, exists from calibre.ptempfile import PersistentTemporaryFile from calibre.constants import DEBUG from shlex import split as shsplit # All files are relative to the OPF location opf_dir = dirname(self.opf) base_dir = dirname(self.pdf_file) base_dir = join(opf_dir, base_dir) try: makedirs(base_dir) except BaseException: if not exists(base_dir): raise # Create a temporary CSS file with the box contents custom_CSS = PersistentTemporaryFile() custom_CSS.write(unicode(self.css1.toPlainText())) custom_CSS.close() # Create a temporary file with the list of input files file_list = PersistentTemporaryFile() for item in self.oeb.spine: file_list.write(item.href + "\n") file_list.close() # Build the command line command = prefs['prince_exe'] args = ['-v'] if self.prince_file: args.append('-s') args.append(self.prince_file) args.append('-s') args.append(custom_CSS.name) args.append('-l') args.append(file_list.name) args.append('-o') args.append(self.pdf_file) # Additional command-line arguments args.extend(shsplit(self.args.text())) # Hide the convert button and show a busy indicator self.convert.setEnabled(False) self.progress_bar = QProgressBar() self.progress_bar.setRange(0,0) self.progress_bar.setValue(0) self.l.addWidget(self.progress_bar) # Run the command and return the path to the PDF file if DEBUG: print(_('Converting book...')) process = QProcess(self) process.setWorkingDirectory(opf_dir) process.setProcessChannelMode(QProcess.MergedChannels); process.error.connect(self.error) process.finished.connect(self.end) self.process = process if DEBUG: from subprocess import list2cmdline line = list2cmdline([command] + args) print(_('Command line: %s') % line) process.start(command, args) def error(self, rc): ''' Show a message when there is an error in the command :param rc: The error code ''' from calibre.gui2 import error_dialog # Remove the progress bar while the error message is displayed self.progress_bar.hide() self.progress_bar.deleteLater() error_dialog(self, _('Process error'), _('<p>Error code: %s' '<p>make sure Prince (<a href="http://www.princexml.com">www.princexml.com</a>) is installed ' 'and the correct command-line-interface executable is set in the configuration of this plugin, ' 'which is usually:' '<ul><li>In Windows: <code><i>Prince_folder</i>\\Engine\\bin\\prince.exe</code>' ' <li>In Linux: <code>prince</code>' '</ul>') % rc, show=True) self.pdf_file = None self.accept() def end(self, rc): ''' Close and return the filename when the process ends :param rc: The return code (0 if successful) ''' from os.path import join self.prince_log = unicode(self.process.readAllStandardOutput().data()) opf_dir = unicode(self.process.workingDirectory()) if (rc == 0): self.pdf_file = join(opf_dir, self.pdf_file) else: self.pdf_file = None self.accept()
class XArmUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(XArmUI, self).__init__() self.handler = XArmHandler(self) self.lang = self.main_ui.lang self.set_ui() self.set_disable(True) def set_ui(self): self._set_common_top_ui() self._set_tab() self._set_common_down_ui() self.connect_slot() def _set_common_top_ui(self): top_frame = QFrame() top_frame.setMaximumHeight(60) top_layout = QVBoxLayout(top_frame) self.layout.addWidget(top_frame) common_top_frame = QFrame() common_top_frame.setMinimumHeight(50) common_top_layout = QHBoxLayout(common_top_frame) top_layout.addWidget(common_top_frame) label_1 = QLabel(i18n[self.lang]['Connected'] + ':') self.label_connected = QLabel() img = QImage() self.label_connected.setMaximumHeight(20) self.label_connected.setMaximumWidth(20) self.label_connected.setScaledContents(True) if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) label_2 = QLabel(i18n[self.lang]['Reported'] + ':') self.label_reported = QLabel() img = QImage() self.label_reported.setMaximumHeight(20) self.label_reported.setMaximumWidth(20) self.label_reported.setScaledContents(True) if img.load(disconnect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) self.lnt_addr = QLineEdit('192.168.1.182') self.lnt_addr.setMaximumWidth(100) self.lnt_addr.setMinimumWidth(60) self.btn_connect = QPushButton(i18n[self.lang]['Connect']) # self.btn_connect.setMaximumWidth(50) # common_top_layout.addStretch(0) common_top_layout.setSpacing(10) common_top_layout.addWidget(label_1) common_top_layout.addWidget(self.label_connected) common_top_layout.addWidget(label_2) common_top_layout.addWidget(self.label_reported) common_top_layout.addWidget(self.lnt_addr) common_top_layout.addWidget(self.btn_connect) # common_down_frame = QFrame() # common_down_layout = QHBoxLayout(common_down_frame) # common_down_layout.setSpacing(0) # top_layout.addWidget(common_down_frame) common_down_layout = common_top_layout label = QLabel(i18n[self.lang]['WarnCode'] + ':') self.label_warn_code = QLabel('0') self.label_warn_code.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_warn_code) label = QLabel(i18n[self.lang]['ErrorCode'] + ':') self.label_error_code = QLabel('0') self.label_error_code.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_error_code) label = QLabel(i18n[self.lang]['CmdCount'] + ':') self.label_cmd_count = QLabel('0') self.label_cmd_count.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_cmd_count) label = QLabel(i18n[self.lang]['State'] + ':') self.label_state = QLabel('4') self.label_state.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_state) label = QLabel(i18n[self.lang]['Maable'] + ':') self.label_maable = QLabel('128') self.label_maable.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_maable) label = QLabel(i18n[self.lang]['Mtbrake'] + ':') self.label_mtbrake = QLabel('128') self.label_mtbrake.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_mtbrake) def _set_tab(self): tab_widget = QTabWidget() tab_widget.setMaximumHeight(self.main_ui.window.geometry().height() // 2) self.layout.addWidget(tab_widget) toolBox1 = QToolBox() toolBox2 = QToolBox() groupBox1 = QGroupBox() groupBox2 = QGroupBox() toolBox1.addItem(groupBox1, "") toolBox2.addItem(groupBox2, "") tab_widget.addTab(toolBox1, i18n[self.lang]['Joint']) tab_widget.addTab(toolBox2, i18n[self.lang]['Cartesian']) joint_layout = QVBoxLayout(groupBox1) cartesian_layout = QVBoxLayout(groupBox2) self.cartesian_ui = CartesianUI(self, cartesian_layout) self.axis_ui = JointUI(self, joint_layout) def _set_common_down_ui(self): slider_frame = QFrame() slider_layout = QGridLayout(slider_frame) self.layout.addWidget(slider_frame) label = QLabel(i18n[self.lang]['Speed'] + ':') self.slider_speed = QSlider(Qt.Horizontal) self.spinbox_speed = QSpinBox() self.slider_speed.setMinimum(1) self.slider_speed.setMaximum(1000) self.slider_speed.setValue(50) self.spinbox_speed.setSingleStep(1) self.spinbox_speed.setMinimum(1) self.spinbox_speed.setMaximum(1000) self.spinbox_speed.setValue(50) slider_layout.addWidget(label, 0, 0) slider_layout.addWidget(self.slider_speed, 0, 1) slider_layout.addWidget(self.spinbox_speed, 0, 2) label = QLabel(i18n[self.lang]['Acc'] + ':') self.slider_acc = QSlider(Qt.Horizontal) self.spinbox_acc = QSpinBox() self.slider_acc.setMinimum(1) self.slider_acc.setMaximum(100000) self.slider_acc.setValue(5000) self.spinbox_acc.setSingleStep(1) self.spinbox_acc.setMinimum(1) self.spinbox_acc.setMaximum(100000) self.spinbox_acc.setValue(5000) slider_layout.addWidget(label, 0, 3) slider_layout.addWidget(self.slider_acc, 0, 4) slider_layout.addWidget(self.spinbox_acc, 0, 5) common_frame = QFrame() common_layout = QGridLayout(common_frame) self.layout.addWidget(common_frame) self.btn_stop = QPushButton(i18n[self.lang]['Stop']) self.btn_clean = QPushButton(i18n[self.lang]['CleanErrorWarn']) self.btn_reset = QPushButton(i18n[self.lang]['Reset']) self.btn_get_servo_dbmsg = QPushButton( i18n[self.lang]['GetServoDebugMsg']) common_layout.addWidget(self.btn_stop, 0, 0) common_layout.addWidget(self.btn_clean, 0, 2) common_layout.addWidget(self.btn_reset, 0, 3) common_layout.addWidget(self.btn_get_servo_dbmsg, 0, 4) btn_frame = QFrame() btn_layout = QGridLayout(btn_frame) self.layout.addWidget(btn_frame) self.combobox_servo = QComboBox() self.combobox_servo.setStyleSheet('''color: blue;''') for item in [ 'axis-all', 'axis-1', 'axis-2', 'axis-3', 'axis-4', 'axis-5', 'axis-6', 'axis-7' ]: self.combobox_servo.addItem(item) self.combobox_servo.setCurrentIndex(1) btn_layout.addWidget(self.combobox_servo, 0, 0) self.btn_motion_enable = QPushButton(i18n[self.lang]['MotionEnable']) self.btn_motion_disable = QPushButton(i18n[self.lang]['MotionDisable']) self.btn_servo_attach = QPushButton(i18n[self.lang]['ServoAttach']) self.btn_servo_detach = QPushButton(i18n[self.lang]['ServoDetach']) self.combobox_state = QComboBox() self.combobox_state.setStyleSheet('''color: blue;''') for item in ['sport', 'pause', 'stop']: self.combobox_state.addItem(item) self.combobox_state.setCurrentIndex(0) self.btn_set_state = QPushButton(i18n[self.lang]['SetState']) btn_layout.addWidget(self.btn_motion_enable, 0, 1) btn_layout.addWidget(self.btn_motion_disable, 0, 2) btn_layout.addWidget(self.btn_servo_attach, 0, 3) btn_layout.addWidget(self.btn_servo_detach, 0, 4) btn_layout.addWidget(self.combobox_state, 0, 5) btn_layout.addWidget(self.btn_set_state, 0, 6) self.lnt_servo_addr = QLineEdit('servo_addr') self.lnt_servo_addr_value = QLineEdit('value') self.btn_get_servo_addr16 = QPushButton( i18n[self.lang]['GetServoAddr16']) self.btn_set_servo_addr16 = QPushButton( i18n[self.lang]['SetServoAddr16']) self.btn_get_servo_addr32 = QPushButton( i18n[self.lang]['GetServoAddr32']) self.btn_set_servo_addr32 = QPushButton( i18n[self.lang]['SetServoAddr32']) self.btn_set_servo_zero = QPushButton(i18n[self.lang]['SetServoZero']) btn_layout.addWidget(self.lnt_servo_addr, 1, 0) btn_layout.addWidget(self.lnt_servo_addr_value, 1, 1) btn_layout.addWidget(self.btn_get_servo_addr16, 1, 2) btn_layout.addWidget(self.btn_set_servo_addr16, 1, 3) btn_layout.addWidget(self.btn_get_servo_addr32, 1, 4) btn_layout.addWidget(self.btn_set_servo_addr32, 1, 5) btn_layout.addWidget(self.btn_set_servo_zero, 1, 6) def connect_slot(self): self.btn_connect.clicked.connect(self.connect) self.slider_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_speed, scale=1)) self.spinbox_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_speed, scale=1)) self.slider_acc.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_acc, scale=1)) self.spinbox_acc.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_acc, scale=1)) self.btn_stop.clicked.connect(self.stop) self.btn_clean.clicked.connect(self.clean) self.btn_reset.clicked.connect(self.reset) self.btn_get_servo_dbmsg.clicked.connect( functools.partial(self.handler.get_servo_debug_msg, only_log_error_servo=False)) self.btn_motion_enable.clicked.connect(self.motion_enable) self.btn_motion_disable.clicked.connect(self.motion_disable) self.btn_servo_attach.clicked.connect(self.set_servo_attach) self.btn_servo_detach.clicked.connect(self.set_servo_detach) self.btn_set_state.clicked.connect(self.set_state) self.btn_get_servo_addr16.clicked.connect(self.get_servo_addr_16) self.btn_set_servo_addr16.clicked.connect(self.set_servo_addr_16) self.btn_get_servo_addr32.clicked.connect(self.get_servo_addr_32) self.btn_set_servo_addr32.clicked.connect(self.set_servo_addr_32) self.btn_set_servo_zero.clicked.connect(self.set_servo_zero) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def reset_flag(self): self.cartesian_ui.reset_flag() self.axis_ui.reset_flag() def update_maable_mtbrake(self, maable, mtbrake): try: self.label_maable.setText(str(maable)) self.label_mtbrake.setText(str(mtbrake)) self.label_maable.setStyleSheet('''color: green;font:bold;''') self.label_mtbrake.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def update_cmd_count(self, cmdnum): try: self.label_cmd_count.setText(str(cmdnum)) self.label_cmd_count.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def update_state(self, state): try: if state == 1: state_str = 'sport' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: green;font:bold;''') elif state == 2: state_str = 'sleep' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: gray;font:bold;''') elif state == 3: state_str = 'pause' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: orange;font:bold;''') elif state == 4: state_str = 'stop' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: red;font:bold;''') except Exception as e: print(e) # getattr(self, 'label_state').setText(state_str) # getattr(self, 'label_state').setText(str(state)) if state != 1: self.reset_flag() def update_warn_error(self, item): try: warn, error = item self.label_warn_code.setText(str(warn)) self.label_error_code.setText(str(error)) if warn != 0: self.label_warn_code.setStyleSheet('''color: red;font:bold;''') else: self.label_warn_code.setStyleSheet( '''color: green;font:bold;''') if error != 0: self.label_error_code.setStyleSheet( '''color: red;font:bold;''') else: self.label_error_code.setStyleSheet( '''color: green;font:bold;''') except Exception as e: print(e) def update_connect_status(self, item): try: img = QImage() if item[0]: logger.info('connect to {} success, report: {}'.format( self.handler.addr, self.handler.report_type)) if img.load(connect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Disconnect']) self.btn_connect.setStyleSheet('''color: red;font:bold;''') self.set_disable(False) else: logger.info('disconnect from or failed connect {}'.format( self.handler.addr)) self.handler.cmd_que.queue.clear() if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet( '''color: green;font:bold;''') self.set_disable(True) if item[1]: if img.load(connect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) else: if img.load(disconnect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) except Exception as e: print(e) def connect(self, event): try: if str(self.btn_connect.text()) == i18n[self.lang]['Connect']: addr = self.lnt_addr.text().strip() if addr == '192.168.1.': addr = 'localhost' report_type = 'normal' else: tmp = addr.split(':') addr = tmp[0] report_type = tmp[1] if len(tmp) > 1 else 'normal' self.btn_connect.setText('Connecting') self.btn_connect.setStyleSheet('''color: orange;font:bold;''') self.handler.connect(addr, report_type=report_type) # if self.window.connect(addr, report_type=report_type): # self.btn_connect.setText(self.disconnect_label) # self.btn_connect.setStyleSheet('''color: red;font:bold;''') elif str(self.btn_connect.text()) == i18n[self.lang]['Disconnect']: self.handler.disconnect() self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def stop(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': 0, 'enable': True } } self.handler.put_cmd_que(item) item = { 'cmd': 'urgent_stop', } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) def clean(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) except Exception as e: print(e) def reset(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': 0, 'enable': True } } self.handler.put_cmd_que(item) item = {'cmd': 'set_state', 'kwargs': {'state': 0}} self.handler.put_cmd_que(item) item = { 'cmd': 'move_gohome', 'kwargs': { 'speed': 30, 'mvacc': 5000, } } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) def get_servo_addr_16(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要获取电机{}的地址{}的值吗?'.format(servo_id, addr) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'get_servo_addr_16', 'kwargs': { 'servo_id': servo_id, 'addr': addr } } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_servo_addr_32(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要获取电机{}的地址{}的值吗?'.format(servo_id, addr) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'get_servo_addr_32', 'kwargs': { 'servo_id': servo_id, 'addr': addr } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_addr_16(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return value = self.lnt_servo_addr_value.text().strip() try: value = float(value) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的值, 值必须是float32类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要设置电机{}的地址{}的值为{}吗?'.format(servo_id, addr, value) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_addr_16', 'kwargs': { 'servo_id': servo_id, 'addr': addr, 'value': value } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_addr_32(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return value = self.lnt_servo_addr_value.text().strip() try: value = float(value) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的值, 值必须是float32类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要设置电机{}的地址{}的值为{}吗?'.format(servo_id, addr, value) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_addr_32', 'kwargs': { 'servo_id': servo_id, 'addr': addr, 'value': value } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_zero(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) if servo_id == 8: tmp = '你确定要设置所有电机的零点吗?' else: tmp = '你确定要设置电机{}的零点吗?'.format(servo_id) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_zero', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_attach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) item = { 'cmd': 'set_servo_attach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': servo_id, 'enable': True } } self.handler.put_cmd_que(item) item = {'cmd': 'set_state', 'kwargs': {'state': 0}} self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_detach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) if servo_id == 8: tmp = '你确定要解锁所有电机吗?' else: tmp = '你确定要解锁电机{}吗?'.format(servo_id) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_detach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def motion_enable(self, event): self._motion_enable(True) def motion_disable(self, event): self._motion_enable(False) def _motion_enable(self, enable=True): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': servo_id, 'enable': enable } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_state(self, event): try: text = self.combobox_state.currentText() if text == 'sport': state = 0 elif text == 'pause': state = 3 elif text == 'stop': state = 4 else: return if state in [0, 3, 4]: item = {'cmd': 'set_state', 'kwargs': {'state': state}} self.handler.put_cmd_que(item) except Exception as e: print(e) def set_disable(self, disable): try: self.btn_stop.setDisabled(disable) self.btn_clean.setDisabled(disable) self.btn_reset.setDisabled(disable) self.btn_get_servo_dbmsg.setDisabled(disable) self.combobox_servo.setDisabled(disable) self.combobox_state.setDisabled(disable) self.btn_motion_enable.setDisabled(disable) self.btn_motion_disable.setDisabled(disable) self.btn_servo_attach.setDisabled(disable) self.btn_servo_detach.setDisabled(disable) self.btn_set_state.setDisabled(disable) self.lnt_servo_addr.setDisabled(disable) self.lnt_servo_addr_value.setDisabled(disable) self.btn_get_servo_addr16.setDisabled(disable) self.btn_set_servo_addr16.setDisabled(disable) self.btn_get_servo_addr32.setDisabled(disable) self.btn_set_servo_addr32.setDisabled(disable) self.btn_set_servo_zero.setDisabled(disable) self.slider_speed.setDisabled(disable) self.spinbox_speed.setDisabled(disable) self.slider_acc.setDisabled(disable) self.spinbox_acc.setDisabled(disable) self.axis_ui.set_disable(disable) self.cartesian_ui.set_disable(disable) except Exception as e: print(e)
class ConfigWidget(QWidget): # GUI definition def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.ll = QHBoxLayout() self.l.addLayout(self.ll) self.label_exe = QLabel(_('&Prince executable:')) self.ll.addWidget(self.label_exe) self.exe = QLineEdit(self) self.exe.setText(prefs['prince_exe']) self.exe.setToolTip(_('<qt>Executable for the Prince program (command-line interface)</qt>')) self.ll.addWidget(self.exe) self.label_exe.setBuddy(self.exe) self.browse = QPushButton(_('&Browse') + '...', self) self.browse.setToolTip(_('<qt>Search the Prince executable in your computer</qt>')) self.browse.clicked.connect(self.select_exe) self.ll.addWidget(self.browse) self.lll = QHBoxLayout() self.l.addLayout(self.lll) self.label_fmts = QLabel(_('Preferred &formats:')) self.lll.addWidget(self.label_fmts) self.fmts = QLineEdit(self) self.fmts.setText(','.join(prefs['formats'])) self.fmts.setToolTip(_('<qt>Comma-separated list of preferred formats to use as source, the first that matches will be used</qt>')) self.lll.addWidget(self.fmts) self.label_fmts.setBuddy(self.fmts) self.add_book = QCheckBox(_('&Add PDF to the book record')) self.add_book.setToolTip(_('<qt>Add the converted PDF to the selected book record</qt>')) self.add_book.setChecked(prefs['add_book']) self.l.addWidget(self.add_book) self.show_css = QCheckBox(_('&Show CSS in the Convert dialog')) self.show_css.setToolTip(_('<qt>Show by default the stylesheets in the Convert dialog</qt>')) self.show_css.setChecked(prefs['show_CSS']) self.l.addWidget(self.show_css) self.css_layout = QVBoxLayout() self.llll = QHBoxLayout() self.css_layout.addLayout(self.llll) self.css_list = QComboBox() self.css_list.setToolTip(_('<qt>List of custom stylesheets defined. Select one to edit</qt>')) self.css_list.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.CSS_list = prefs['custom_CSS_list'].copy() self.default_CSS = prefs['default_CSS'] if 'custom_CSS' in prefs: self.CSS_list[_('old')] = prefs['custom_CSS'] self.default_CSS = _('old') if self.default_CSS not in self.CSS_list: self.default_CSS = sorted(self.CSS_list, key=lambda x: x.lower())[0] for key in sorted(self.CSS_list, key=lambda x: x.lower()): self.css_list.addItem(key, key) self.css_list.setCurrentIndex(self.css_list.findText(self.default_CSS)) self.css_list.currentIndexChanged.connect(self.set_css) self.llll.addWidget(self.css_list) self.css_rename = QPushButton(_('Re&name')) self.css_rename.setToolTip(_('<qt>Rename the current stylesheet to the name on the right</qt>')) self.css_rename.clicked.connect(self.rename_css) self.css_rename.setEnabled(False) self.llll.addWidget(self.css_rename) self.css_name = QLineEdit(self) self.css_name.setToolTip(_('<qt>Name for the new or renamed stylesheet</qt>')) self.css_name.setText(self.css_list.currentText()) self.css_name.textChanged.connect(self.check_names) self.llll.addWidget(self.css_name) self.css_add = QPushButton(_('A&dd')) self.css_add.setToolTip(_('<qt>Add a new empty stylesheet with the name on the left</qt>')) self.css_add.clicked.connect(self.add_css) self.css_add.setEnabled(False) self.llll.addWidget(self.css_add) self.css_remove = QPushButton(_('Re&move')) self.css_remove.setToolTip(_('<qt>Remove the current stylesheet</qt>')) self.css_remove.clicked.connect(self.remove_css) self.llll.addWidget(self.css_remove) self.css = TextEditWithTooltip() self.css.setLineWrapMode(TextEditWithTooltip.NoWrap) self.css.load_text(self.CSS_list[unicode(self.css_list.currentText())],'css') self.css.setToolTip(_('<qt>Custom stylesheet that will be applied, if selected, to all Prince PDF conversions</qt>')) self.css_layout.addWidget(self.css) self.css_templates = QLabel(_('Book metadata can be used in the stylesheet. Anything between %(s1)s and %(s2)s will be processed as a calibre template. For instance, %(s3)s in the stylesheet will be replaced with the book title in the conversion.') % \ {'s1':'<span style="font-family:monospace ; font-weight:bold">@{@</span>', \ 's2':'<span style="font-family:monospace ; font-weight:bold">@}@</span>', \ 's3':'<span style="font-family:monospace ; font-weight:bold">@{@{title}@}@</span>'}) self.css_templates.setWordWrap(True) self.css_layout.addWidget(self.css_templates) self.css_box = QGroupBox(_('&Custom CSS:')) self.css_box.setLayout(self.css_layout) self.l.addWidget(self.css_box) self.lllll = QHBoxLayout() self.lllll.setAlignment(Qt.AlignLeft) self.l.addLayout(self.lllll) self.defaults = QPushButton(_('&Restore defaults')) self.defaults.setToolTip(_('<qt>Restore the default settings</qt>')) self.defaults.clicked.connect(self.restore_defaults) self.lllll.addWidget(self.defaults, alignment=Qt.AlignLeft) self.warning = QLabel(_('<b>Warning</b>: Deletes modified stylesheets')) self.lllll.addWidget(self.warning) self.adjustSize() def select_exe(self): ''' Create a dialog to select the Prince executable ''' dialog = QFileDialog() dialog.setFileMode(QFileDialog.ExistingFile) filename = dialog.getOpenFileName(self, _('Select Prince executable'), '', '') if filename: try: self.exe.setText(filename) except(TypeError): self.exe.setText(filename[0]) def restore_defaults(self): ''' Restore the default settings ''' self.exe.setText(prefs.defaults['prince_exe']) self.fmts.setText(','.join(prefs.defaults['formats']).lower()) self.show_css.setChecked(prefs.defaults['show_CSS']) self.add_book.setChecked(prefs.defaults['add_book']) self.css_list.currentIndexChanged.disconnect() self.css_list.clear() self.CSS_list = prefs.defaults['custom_CSS_list'].copy() self.default_CSS = prefs.defaults['default_CSS'] for key in sorted(self.CSS_list, key=lambda x: x.lower()): self.css_list.addItem(key, key) self.css_list.setCurrentIndex(self.css_list.findText(self.default_CSS)) self.css_name.setText(self.default_CSS) self.css.load_text(self.CSS_list[unicode(self.css_list.currentText())],'css') self.css_list.currentIndexChanged.connect(self.set_css) def save_settings(self): ''' Save the current settings ''' prefs['prince_exe'] = unicode(self.exe.text()) prefs['formats'] = unicode(self.fmts.text().lower()).split(',') prefs['show_CSS'] = self.show_css.isChecked() prefs['add_book'] = self.add_book.isChecked() self.set_css() prefs['default_CSS'] = self.default_CSS prefs['custom_CSS_list'] = self.CSS_list.copy() if 'custom_CSS' in prefs: del prefs['custom_CSS'] def set_css(self): ''' Fill the CSS text box with the selected stylesheet ''' self.CSS_list[self.default_CSS] = unicode(self.css.toPlainText()) self.default_CSS = unicode(self.css_list.currentText()) self.css.load_text(self.CSS_list[self.default_CSS],'css') self.css_name.setText(self.css_list.currentText()) def add_css(self): ''' Add a new stylesheet ''' from calibre.gui2 import error_dialog name = unicode(self.css_name.text()) if name in self.CSS_list: error_dialog(self, _('Cannot add stylesheet'), _('A stylesheet with the name "%s" is already defined, use a different name.') % name, show=True) else: self.CSS_list[name] = '' self.css_list.addItem(name, name) self.css_list.setCurrentIndex(self.css_list.findText(name)) self.css_add.setEnabled(False) self.css_rename.setEnabled(False) def remove_css(self): ''' Remove an existing stylesheet ''' from calibre.gui2 import error_dialog if (self.css_list.count() > 1): self.css_list.currentIndexChanged.disconnect() self.css_list.removeItem(self.css_list.currentIndex()) del self.CSS_list[self.default_CSS] self.default_CSS = unicode(self.css_list.currentText()) self.css.load_text(self.CSS_list[self.default_CSS],'css') self.css_list.currentIndexChanged.connect(self.set_css) self.css_name.setText(self.css_list.currentText()) else: error_dialog(self, _('Cannot delete the last stylesheet'), _('The last stylesheet cannot be removed. You can rename it and/or remove its contents.'), show=True) def rename_css(self): ''' Rename a stylesheet ''' from calibre.gui2 import error_dialog name = unicode(self.css_name.text()) if name in self.CSS_list: error_dialog(self, _('Cannot rename stylesheet'), _('A stylesheet with the name "%s" is already defined, use a different name.') % name, show=True) else: self.CSS_list[name] = self.CSS_list.pop(self.default_CSS) self.css_list.setItemText(self.css_list.currentIndex(),name) self.default_CSS = name def check_names(self, text): name = unicode(text) if name in self.CSS_list: self.css_add.setEnabled(False) self.css_rename.setEnabled(False) else: self.css_add.setEnabled(True) self.css_rename.setEnabled(True)
class CreateVirtualLibrary(QDialog): # {{{ def __init__(self, gui, existing_names, editing=None): QDialog.__init__(self, gui) self.gui = gui self.existing_names = existing_names if editing: self.setWindowTitle(_('Edit virtual library')) else: self.setWindowTitle(_('Create virtual library')) self.setWindowIcon(QIcon(I('lt.png'))) gl = QGridLayout() self.setLayout(gl) self.la1 = la1 = QLabel(_('Virtual library &name:')) gl.addWidget(la1, 0, 0) self.vl_name = QComboBox() self.vl_name.setEditable(True) self.vl_name.lineEdit().setMaxLength(MAX_VIRTUAL_LIBRARY_NAME_LENGTH) la1.setBuddy(self.vl_name) gl.addWidget(self.vl_name, 0, 1) self.editing = editing self.saved_searches_label = QLabel('') self.saved_searches_label.setTextInteractionFlags(Qt.TextSelectableByMouse) gl.addWidget(self.saved_searches_label, 2, 0, 1, 2) self.la2 = la2 = QLabel(_('&Search expression:')) gl.addWidget(la2, 1, 0) self.vl_text = QLineEdit() self.vl_text.textChanged.connect(self.search_text_changed) la2.setBuddy(self.vl_text) gl.addWidget(self.vl_text, 1, 1) self.vl_text.setText(_build_full_search_string(self.gui)) self.sl = sl = QLabel('<p>'+_('Create a virtual library based on: ')+ ('<a href="author.{0}">{0}</a>, ' '<a href="tag.{1}">{1}</a>, ' '<a href="publisher.{2}">{2}</a>, ' '<a href="series.{3}">{3}</a>, ' '<a href="search.{4}">{4}</a>.').format(_('Authors'), _('Tags'), _('Publishers'), _('Series'), _('Saved Searches'))) sl.setWordWrap(True) sl.setTextInteractionFlags(Qt.LinksAccessibleByMouse) sl.linkActivated.connect(self.link_activated) gl.addWidget(sl, 3, 0, 1, 2) gl.setRowStretch(3,10) self.hl = hl = QLabel(_(''' <h2>Virtual Libraries</h2> <p>Using <i>virtual libraries</i> you can restrict calibre to only show you books that match a search. When a virtual library is in effect, calibre behaves as though the library contains only the matched books. The Tag Browser display only the tags/authors/series/etc. that belong to the matched books and any searches you do will only search within the books in the virtual library. This is a good way to partition your large library into smaller and easier to work with subsets.</p> <p>For example you can use a Virtual Library to only show you books with the Tag <i>"Unread"</i> or only books by <i>"My Favorite Author"</i> or only books in a particular series.</p> <p>More information and examples are available in the <a href="%s">User Manual</a>.</p> ''') % localize_user_manual_link('http://manual.calibre-ebook.com/virtual_libraries.html')) hl.setWordWrap(True) hl.setOpenExternalLinks(True) hl.setFrameStyle(hl.StyledPanel) gl.addWidget(hl, 0, 3, 4, 1) bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) gl.addWidget(bb, 4, 0, 1, 0) if editing: db = self.gui.current_db virt_libs = db.prefs.get('virtual_libraries', {}) for dex,vl in enumerate(sorted(virt_libs.keys(), key=sort_key)): self.vl_name.addItem(vl, virt_libs.get(vl, '')) if vl == editing: self.vl_name.setCurrentIndex(dex) self.original_index = dex self.original_search = virt_libs.get(editing, '') self.vl_text.setText(self.original_search) self.new_name = editing self.vl_name.currentIndexChanged[int].connect(self.name_index_changed) self.vl_name.lineEdit().textEdited.connect(self.name_text_edited) self.resize(self.sizeHint()+QSize(150, 25)) def search_text_changed(self, txt): db = self.gui.current_db searches = [_('Saved searches recognized in the expression:')] txt = unicode(txt) while txt: p = txt.partition('search:') if p[1]: # found 'search:' possible_search = p[2] if possible_search: # something follows the 'search:' if possible_search[0] == '"': # strip any quotes possible_search = possible_search[1:].partition('"') else: # find end of the search name. Is EOL, space, rparen sp = possible_search.find(' ') pp = possible_search.find(')') if pp < 0 or (sp > 0 and sp <= pp): # space in string before rparen, or neither found possible_search = possible_search.partition(' ') else: # rparen in string before space possible_search = possible_search.partition(')') txt = possible_search[2] # grab remainder of the string search_name = possible_search[0] if search_name.startswith('='): search_name = search_name[1:] if search_name in db.saved_search_names(): searches.append(search_name + '=' + db.saved_search_lookup(search_name)) else: txt = '' else: txt = '' if len(searches) > 1: self.saved_searches_label.setText('\n'.join(searches)) else: self.saved_searches_label.setText('') def name_text_edited(self, new_name): self.new_name = unicode(new_name) def name_index_changed(self, dex): if self.editing and (self.vl_text.text() != self.original_search or self.new_name != self.editing): if not question_dialog(self.gui, _('Search text changed'), _('The virtual library name or the search text has changed. ' 'Do you want to discard these changes?'), default_yes=False): self.vl_name.blockSignals(True) self.vl_name.setCurrentIndex(self.original_index) self.vl_name.lineEdit().setText(self.new_name) self.vl_name.blockSignals(False) return self.new_name = self.editing = self.vl_name.currentText() self.original_index = dex self.original_search = unicode(self.vl_name.itemData(dex) or '') self.vl_text.setText(self.original_search) def link_activated(self, url): db = self.gui.current_db f, txt = unicode(url).partition('.')[0::2] if f == 'search': names = db.saved_search_names() else: names = getattr(db, 'all_%s_names'%f)() d = SelectNames(names, txt, parent=self) if d.exec_() == d.Accepted: prefix = f+'s' if f in {'tag', 'author'} else f if f == 'search': search = ['(%s)'%(db.saved_search_lookup(x)) for x in d.names] else: search = ['%s:"=%s"'%(prefix, x.replace('"', '\\"')) for x in d.names] if search: if not self.editing: self.vl_name.lineEdit().setText(d.names.next()) self.vl_name.lineEdit().setCursorPosition(0) self.vl_text.setText(d.match_type.join(search)) self.vl_text.setCursorPosition(0) def accept(self): n = unicode(self.vl_name.currentText()).strip() if not n: error_dialog(self.gui, _('No name'), _('You must provide a name for the new virtual library'), show=True) return if n.startswith('*'): error_dialog(self.gui, _('Invalid name'), _('A virtual library name cannot begin with "*"'), show=True) return if n in self.existing_names and n != self.editing: if not question_dialog(self.gui, _('Name already in use'), _('That name is already in use. Do you want to replace it ' 'with the new search?'), default_yes=False): return v = unicode(self.vl_text.text()).strip() if not v: error_dialog(self.gui, _('No search string'), _('You must provide a search to define the new virtual library'), show=True) return try: db = self.gui.library_view.model().db recs = db.data.search_getting_ids('', v, use_virtual_library=False, sort_results=False) except ParseException as e: error_dialog(self.gui, _('Invalid search'), _('The search in the search box is not valid'), det_msg=e.msg, show=True) return if not recs and not question_dialog( self.gui, _('Search found no books'), _('The search found no books, so the virtual library ' 'will be empty. Do you really want to use that search?'), default_yes=False): return self.library_name = n self.library_search = v QDialog.accept(self)
class ClassSimplex(QMainWindow): def __init__(self, ui): super(ClassSimplex, self).__init__() self.ui = ui # Simplex self.numVariables = 0 self.numRestricciones = 0 self.columSRcompletas = 0 self.numHolgura = 0 self.numIteraciones = 0 self.solucion_optima = "" self.allTable = [] # Per y Simplex self.asignarComponentes() # Simplex self.editarComponentes() self.eventosDeBotones() def asignarComponentes(self): # Componentes de la interfaz Simplex # Paneles self.panelTablaU = QtWidgets.QFrame self.panelTablaU = self.ui.panelTblU self.panelFunYRest = QtWidgets.QFrame self.panelFunYRest = self.ui.panelVarRest # Etiquetas Labels self.etiquetaIteracion = QtWidgets.QLabel self.etiquetaIteracion = self.ui.lblIteracion self.etiquetaFunObj = QtWidgets.QLabel self.etiquetaFunObj = self.ui.lblFunObj self.etiquetaFuncionObjetivo = QtWidgets.QLabel self.etiquetaFuncionObjetivo = self.ui.lblFuncionObjetivo # Botones self.botonIteracion = QtWidgets.QPushButton self.botonIteracion = self.ui.btnIteracion self.botonPdf = QtWidgets.QPushButton self.botonPdf = self.ui.btnPdf self.botonCalcular = QtWidgets.QPushButton self.botonCalcular = self.ui.btnCalcular self.botonGenerar = QtWidgets.QPushButton self.botonGenerar = self.ui.btnGenerar # Campos de texto self.textFieldVar = QtWidgets.QLineEdit self.textFieldVar = self.ui.txtVar self.textFieldRestr = QtWidgets.QLineEdit self.textFieldRestr = self.ui.txtRestr # Tablas self.tablaVariables = QtWidgets.QTableWidget self.tablaVariables = self.ui.tblVariables self.tablaRestricciones = QtWidgets.QTableWidget self.tablaRestricciones = self.ui.tblRestricciones self.tablaU = QtWidgets.QTableWidget self.tablaU = self.ui.tbl_U def editarComponentes(self): cmb = QtWidgets.QComboBox panel = QtWidgets.QFrame txt = QtWidgets.QLineEdit self.panelTablaU.setVisible(False) # Ocultar panel self.panelFunYRest.setVisible(False) self.botonPdf.setVisible(False) self.etiquetaFunObj.setVisible(False) def eventosDeBotones(self): self.botonGenerar.clicked.connect(self.cargarProceso) self.botonCalcular.clicked.connect(self.cargarProceso) self.botonIteracion.clicked.connect(self.cargarProceso) self.botonPdf.clicked.connect(self.cargarProceso) def show_popup_Informacion(self, titulo, mensaje): msg = QMessageBox() msg.setWindowTitle(titulo) msg.setIcon(QMessageBox.Information) msg.setText(mensaje) x = msg.exec_() def cargarProceso(self): boton = self.sender() if boton == self.botonGenerar: if not self.textFieldVar.text() or not self.textFieldRestr.text(): self.show_popup_Informacion( "Datos invalidos", "No se ingresaron correctamente los datos") else: self.mostrarLabels(False) self.panelFunYRest.setVisible(True) self.numVariables = int(self.textFieldVar.text()) self.numRestricciones = int(self.textFieldRestr.text()) self.llenarTablaVar() self.llenarTablaRestr() elif boton == self.botonCalcular: if self.validarTablaFuncion() and self.validarTablaRestricciones( ): #validar datos self.allTable = [] self.matrizInicial() self.botonPdf.setVisible(False) elif boton == self.botonIteracion: if self.seguirIteracionesSimplex() == True: self.iteraciones() else: self.botonPdf.setVisible(True) self.show_popup_Informacion( "Mensaje", "Se han terminado las iteraciones") else: self.solucion_optima = self.tablaU.item( (self.numRestricciones + 2), self.columSRcompletas + 1).text() self.generarReporte() def mostrarLabels(self, estado): self.etiquetaFunObj.setVisible(estado) self.etiquetaFuncionObjetivo.setVisible(estado) self.tablaU.clear() self.panelTablaU.setVisible(estado) def llenarTablaVar(self): self.tablaVariables.clear() self.tablaVariables.setRowCount(1) self.tablaVariables.setColumnCount(self.numVariables) for i in range(self.numVariables): item1 = QTableWidgetItem(f"X{i+1}") item1.setBackground(QtGui.QColor(37, 40, 80)) item1.setForeground(QtGui.QColor(255, 255, 255)) self.tablaVariables.setHorizontalHeaderItem(i, item1) def llenarTablaRestr(self): self.tablaRestricciones.clear() self.tablaRestricciones.setRowCount(self.numRestricciones) self.tablaRestricciones.setColumnCount(self.numVariables) for j in range(self.numVariables): item1 = QTableWidgetItem(f"X{j+1}") item1.setBackground(QtGui.QColor(37, 40, 80)) item1.setForeground(QtGui.QColor(255, 255, 255)) self.tablaRestricciones.setHorizontalHeaderItem(j, item1) for i in range(self.numVariables, self.numVariables + 2): item = QTableWidgetItem(" ") self.tablaRestricciones.insertColumn(i) item.setBackground(QtGui.QColor(37, 40, 80)) item.setForeground(QtGui.QColor(255, 255, 255)) self.tablaRestricciones.setHorizontalHeaderItem(i, item) fila = 0 colum = self.numVariables for j in range(self.numRestricciones): self.cmbSigno = QComboBox() self.cmbSigno.addItem("<=") self.tablaRestricciones.setCellWidget(fila, colum, self.cmbSigno) fila += 1 def guardarRestricciones(self): restriccionesString = [" "] * (self.numRestricciones) columnas = self.numVariables + 2 valor = "" # restricciones comboOne = QtWidgets.QComboBox for i in range(0, len(restriccionesString), 1): for j in range(0, columnas, 1): if j < self.numVariables: valor = self.tablaRestricciones.item(i, j).text() if j == 0: restriccionesString[i] = valor + "X" + str(j + 1) else: if valor[0] == '-': restriccionesString[i] += valor + "X" + str(j + 1) else: restriccionesString[i] += "+" + \ valor + "X" + str(j + 1) elif j == self.numVariables: comboOne = self.tablaRestricciones.cellWidget( i, self.numVariables) datoSigno = comboOne.currentText() restriccionesString[i] += datoSigno else: valor = self.tablaRestricciones.item(i, j).text() restriccionesString[i] += valor return restriccionesString def matrizInicial(self): # Guarda las inecuaciones en el arreglo matriz inicial inecuaciones = self.sistemaRestricciones() # Definimos tamaño columnas y filas numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 matriz = [["0"] * numColumnas for i in range(numFilas)] # espacios en blanco y datos que no cambian matriz[0][0] = " " matriz[0][1] = "CJ" matriz[0][numColumnas - 1] = " " matriz[1][0] = "CB" matriz[1][1] = "XB" matriz[1][numColumnas - 1] = "BI" matriz[numFilas - 2][0] = " " matriz[numFilas - 2][1] = "ZJ" matriz[numFilas - 1][0] = " " matriz[numFilas - 1][1] = "ZJ-CJ" matriz[numFilas - 1][numColumnas - 1] = " " # Xb, Cj filas numVar = 0 funcion = "" stringDecimal = "" for j in range(2, (numColumnas - 1), 1): # Cj Xb if numVar < self.numVariables: stringDecimal = self.tablaVariables.item(0, numVar).text() matriz[0][j] = self.devolverValorSR(stringDecimal) # if matriz[0][j] == "Dato vacio": # print("Pendiente Thow Null") funcion += " " + str(matriz[0][j]) matriz[1][j] = "X" + str(numVar + 1) funcion += str(matriz[1][j]) + " +" numVar += 1 elif numVar < self.columSRcompletas: matriz[0][j] = "0" matriz[1][j] = "X" + str(numVar + 1) numVar += 1 self.mostrarLabels(True) minmax = "Max Z = " self.etiquetaFuncionObjetivo.setText(" " + minmax + funcion[0:len(funcion) - 1]) # Guardamos inecuaciones en matriz inicial for q in range(0, self.numRestricciones, 1): # filas for w in range(0, self.columSRcompletas, 1): # columnas matriz[q + 2][w + 2] = str(inecuaciones[q][w]) # Agregar Cb y Xb columnas if str(inecuaciones[q][w]) == "1" and w >= self.numVariables: matriz[q + 2][0] = matriz[0][w + 2] # Cb matriz[q + 2][1] = matriz[1][w + 2] # Xb # Obtener fila zj stringZj = "" acumulaZj = "" for col in range(0, self.columSRcompletas, 1): acumulaZj = "" for fila in range(0, self.numRestricciones, 1): stringZj = self.guardarZj(str(matriz[fila + 2][0]), str(matriz[fila + 2][col + 2])) acumulaZj += stringZj + ";" matriz[numFilas - 2][col + 2] = self.devolverZj(acumulaZj) # obtener fila cj-zj for col in range(2, (numColumnas - 1), 1): matriz[numFilas - 1][col] = self.devolverZjCj( str(matriz[0][col]), str(matriz[numFilas - 2][col])) # mostrar matriz en la tabla self.tablaU.clear() self.tablaU.setRowCount(numFilas) self.tablaU.setColumnCount(numColumnas) for j in range(numColumnas): item1 = QTableWidgetItem(" ") #item1.setBackground(QtGui.QColor(0, 153, 153)) self.tablaU.setHorizontalHeaderItem(j, item1) for row in range(0, numFilas, 1): for col in range(0, numColumnas, 1): item = QTableWidgetItem(str(matriz[row][col])) self.tablaU.setItem(row, col, item) self.tablaU.resizeColumnsToContents() # pintar pivote self.pintarPivote() self.numIteraciones = 0 self.etiquetaIteracion.setText(" " + str(self.numIteraciones)) # Guardar tabla para el pdf fila = self.numRestricciones + 4 columna = self.columSRcompletas + 2 tablaInicial = [] for f in range(fila): filaAnterior = [] for c in range(columna): item = self.tablaU.item(f, c).text() filaAnterior.append(item) tablaInicial.append(filaAnterior) self.allTable.append(tablaInicial) def guardarZj(self, cb, numero): multiCb = "" fracNum = Fraccion.Fraccion(0, 0) fracCB = Fraccion.Fraccion(0, 0) if numero == "0" or cb == "0": multiCb = "0" else: fracNum = fracNum.deTablaFraccion(numero) fracCB = fracCB.deTablaFraccion(cb) multiCb = fracCB.multiplicar(fracNum).__str__() return multiCb def devolverZj(self, acumulaZj): acumulaZj = acumulaZj[0:len(acumulaZj) - 1] # quitar ultimo ; arregloZj = acumulaZj.split(";") zjfinal = "0" fracAcumuladora = Fraccion.Fraccion(0, 1) frac = Fraccion.Fraccion(0, 0) for k in range(0, len(arregloZj), 1): if not arregloZj[k] == "0": fracAcumuladora = fracAcumuladora.sumar( frac.deTablaFraccion(arregloZj[k])) zjfinal = fracAcumuladora.__str__() return zjfinal def devolverZjCj(self, cj, zj): zjcj = "" fraccionZj = Fraccion.Fraccion(0, 0) fraccionCj = Fraccion.Fraccion(0, 0) if cj == "0" and zj == "0": # 0 y 0 zjcj = "0" else: fraccionCj = fraccionCj.deTablaFraccion(cj) if zj[0] == '-': zj = zj[1:len(zj)] else: zj = "-" + zj fraccionZj = fraccionZj.deTablaFraccion(zj) zjcj = fraccionCj.sumar(fraccionZj).__str__() return zjcj def sistemaRestricciones(self): self.columSRcompletas = 0 self.numHolgura = 0 # numero de columnas que ocupan las variables de la funcion objtivo # ciclo que aumenta columnas combo = QtWidgets.QComboBox for i in range(0, self.numRestricciones, 1): self.numHolgura += 1 self.columSRcompletas = self.numVariables + self.numHolgura # Matriz restricciones = [[0] * self.columSRcompletas for i in range(self.numRestricciones)] # Ciclo para agregar los coeficientes de la funcion objetivo stringDecimal1 = "" for iResFila in range(0, self.numRestricciones, 1): for iResCol in range(0, self.numVariables, 1): stringDecimal1 = self.tablaRestricciones.item( iResFila, iResCol).text() restricciones[iResFila][iResCol] = self.devolverValorSR( stringDecimal1) for iResFila in range(0, self.numRestricciones, 1): for iResCol in range(0, self.numHolgura, 1): if iResFila == (iResCol): restricciones[iResFila][iResCol + self.numVariables] = "1" else: restricciones[iResFila][iResCol + self.numVariables] = "0" stringDecimal2 = "" for bi in range(0, self.numRestricciones, 1): stringDecimal2 = self.tablaRestricciones.item( bi, self.tablaRestricciones.columnCount() - 1).text() restricciones[bi][self.columSRcompletas - 1] = self.devolverValorSR(stringDecimal2) return restricciones def devolverValorSR(self, stringDecimal): try: frac = Fraccion.Fraccion(0, 0) decimal = float(1) if stringDecimal == "0" or stringDecimal == "-0" or stringDecimal == "0.0": decimal = 1 elif frac.posicionBarra(stringDecimal) == -1: decimal = float(stringDecimal) else: decimal = 1 try: if decimal % int(decimal) == 0: return stringDecimal else: return frac.toFraccion(decimal).__str__() except ZeroDivisionError: return frac.toFraccion(decimal).__str__() except ValueError: return "Dato vacio" def variableSalida(self): fraccionAij = Fraccion.Fraccion(0, 0) fraccionBi = Fraccion.Fraccion(0, 0) vSal = float(0) siguiente = float(0) numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 menor = 2 # posicion ubicacion ve = self.variableEntrada() # ubicacion de la variable de entrada entra = True # booleana para ejecutarse una sola vez aij = float(0) bi = float(0) stringAij = "" stringBi = "" for i in range(2, (numFilas - 2), 1): # ciclo recorre las filas de las inecuaciones stringAij = self.tablaU.item(i, ve).text() if fraccionAij.posicionBarra(stringAij) == -1: aij = float(stringAij) else: fraccionAij = fraccionAij.deTablaFraccion(stringAij) aij = fraccionAij.toDecimal() stringBi = self.tablaU.item(i, numColumnas - 1).text() if fraccionBi.posicionBarra(stringBi) == -1: bi = float(stringBi) else: fraccionBi = fraccionBi.deTablaFraccion(stringBi) bi = fraccionBi.toDecimal() if (aij > 0) and (bi > 0): # para que no haya division entre 0 siguiente = float(bi / aij) if entra: # solo se ejecuta una vez al inicio del ciclo vSal = siguiente # vSal toma el primer valor de siguiente entra = False menor = i if siguiente < vSal: # condicional para que determinar el menor valor vSal = siguiente menor = i return menor def variableEntrada(self): numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 contador = 3 posicion = 2 # primera posicion fraccionVent = Fraccion.Fraccion(0, 0) fraccionSig = Fraccion.Fraccion(0, 0) vEnt = float(0) siguiente = float(0) stringVent = "" stringSig = "" stringVent = self.tablaU.item(numFilas - 1, 2).text() if fraccionVent.posicionBarra(stringVent) == -1: vEnt = float(stringVent) else: fraccionVent = fraccionVent.deTablaFraccion(stringVent) vEnt = fraccionVent.toDecimal() while contador < numColumnas - 1: # ciclo para hallar stringSig = self.tablaU.item(numFilas - 1, contador).text() if fraccionSig.posicionBarra(stringSig) == -1: siguiente = float(stringSig) else: fraccionSig = fraccionSig.deTablaFraccion(stringSig) siguiente = fraccionSig.toDecimal() if siguiente > vEnt: # si el siguiente valor es menor vEnt = siguiente # vEnt toma ese valor para ser comparado en la siguiente vuelta del ciclo posicion = contador # guarda la ubicacion de la columna contador += 1 return posicion def iteraciones(self): numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 # matriz para tomar los datos actuales de la tabla anteriorIteracion = [[" "] * numColumnas for i in range(numFilas)] # matriz para insertar nuevos datos a la tabla nuevaIteracion = [[" "] * numColumnas for i in range(numFilas)] # llenar matriz anterior for i in range(0, numFilas, 1): for j in range(0, numColumnas, 1): anteriorIteracion[i][j] = self.tablaU.item(i, j).text() # llenar 2 primeras filas de la nueva matriz for k in range(0, 2, 1): for m in range(0, numColumnas, 1): nuevaIteracion[k][m] = self.tablaU.item(k, m).text() col = self.variableEntrada() # ubicacion de la columna del pivote fila = self.variableSalida() # ubicacion de la fila del pivote # obtener fila 1 f1Fila1 = Fraccion.Fraccion(0, 0) f2Fila1 = Fraccion.Fraccion(0, 0) fila1 = [Fraccion.Fraccion(0, 0)] * (numColumnas - 2) string1Fila1 = "" string2Fila1 = "" for i in range(0, len(fila1), 1): string1Fila1 = str(anteriorIteracion[fila][2 + i]) string2Fila1 = str(anteriorIteracion[fila][col]) f1Fila1 = f1Fila1.deTablaFraccion(string1Fila1) fila1[i] = f1Fila1.dividir(f2Fila1.deTablaFraccion(string2Fila1)) # obtener las otras filas 0 stringNega = "" stringFila0 = "" fracNega = Fraccion.Fraccion(0, 0) fracFila0 = Fraccion.Fraccion(0, 0) fracMulti0 = Fraccion.Fraccion(0, 0) multiplicador = "" for iterador in range(2, (numFilas - 2), 1): if not iterador == fila: # si se cumpla se calcula el valor de las nuevas filas 0 for j in range(2, numColumnas, 1): stringNega = str(anteriorIteracion[iterador][col]) fracNega = fracNega.deTablaFraccion(stringNega) fracNega = fracNega.multiplicar(Fraccion.Fraccion(-1, 1)) stringFila0 = str(anteriorIteracion[iterador][j]) fracFila0 = fracFila0.deTablaFraccion(stringFila0) fracMulti0 = fila1[j - 2].multiplicar(fracNega) fracMulti0 = fracMulti0.sumar(fracFila0) nuevaIteracion[iterador][j] = fracMulti0.__str__() else: # si no se cumple se guarda la fila 1 donde corresponde for j in range(2, numColumnas, 1): nuevaIteracion[iterador][j] = fila1[j - 2].__str__() # llenar CB y XB for icb in range(2, (numFilas - 2), 1): for ixb in range(0, 2, 1): if icb == fila: nuevaIteracion[fila][ixb] = anteriorIteracion[ixb][col] else: nuevaIteracion[icb][ixb] = anteriorIteracion[icb][ixb] # llenar Zj nuevaIteracion[numFilas - 2][0] = anteriorIteracion[numFilas - 2][0] # " " nuevaIteracion[numFilas - 2][1] = anteriorIteracion[numFilas - 2][1] # "Zj" stringZj = "" acumulaZj = "" for i in range(2, numColumnas, 1): acumulaZj = "" for j in range(2, (numFilas - 2), 1): stringZj = self.guardarZj(str(nuevaIteracion[j][0]), str(nuevaIteracion[j][i])) acumulaZj += stringZj + ";" nuevaIteracion[numFilas - 2][i] = self.devolverZj(acumulaZj) # llenar Cj-Zj nuevaIteracion[numFilas - 1][0] = anteriorIteracion[numFilas - 1][0] # " " nuevaIteracion[numFilas - 1][1] = anteriorIteracion[numFilas - 1][1] # "Zj-Cj" nuevaIteracion[numFilas - 1][numColumnas - 1] = anteriorIteracion[numFilas - 1][numColumnas - 1] # " " stringA = "" stringB = "" for i in range(2, (numColumnas - 1), 1): stringA = str(nuevaIteracion[0][i]) stringB = str(nuevaIteracion[numFilas - 2][i]) nuevaIteracion[numFilas - 1][i] = self.devolverZjCj( stringA, stringB) # mostrar matriz en la tabla self.tablaU.clear() self.tablaU.setRowCount(numFilas) self.tablaU.setColumnCount(numColumnas) for j in range(numColumnas): item1 = QTableWidgetItem(" ") self.tablaU.setHorizontalHeaderItem(j, item1) for row in range(0, numFilas, 1): for colT in range(0, numColumnas, 1): item = QTableWidgetItem(str(nuevaIteracion[row][colT])) self.tablaU.setItem(row, colT, item) self.tablaU.resizeColumnsToContents() # pintar pivote self.pintarPivote() self.numIteraciones += 1 self.etiquetaIteracion.setText(" " + str(self.numIteraciones)) # Guardar tabla para el pdf fila = self.numRestricciones + 4 columna = self.columSRcompletas + 2 tablaItera = [] for f in range(fila): filaAnterior = [] for c in range(columna): item = self.tablaU.item(f, c).text() filaAnterior.append(item) tablaItera.append(filaAnterior) self.allTable.append(tablaItera) def seguirIteracionesSimplex(self): seSigue = False numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 stringSig = "" siguiente = float(0) fraccionSig = Fraccion.Fraccion(0, 0) for i in range(2, (numColumnas - 2), 1): stringSig = self.tablaU.item(numFilas - 1, i).text() if fraccionSig.posicionBarra(stringSig) == -1: siguiente = float(stringSig) else: fraccionSig = fraccionSig.deTablaFraccion(stringSig) siguiente = fraccionSig.toDecimal() if siguiente > 0: seSigue = True return seSigue def pintarPivote(self): fila = self.variableSalida() # ubicacion de la variable de salida col = self.variableEntrada() # ubicacion de la variable de entrada pivote = self.tablaU.item(fila, col).text() item = QTableWidgetItem(str(pivote)) item.setBackground(QtGui.QColor(244, 67, 54)) self.tablaU.setItem(fila, col, item) def generarReporte(self): fila = self.numRestricciones + 4 columna = self.columSRcompletas + 2 tituloReporte = "Reporte_Metodo_Simplex.pdf" try: doc = SimpleDocTemplate(tituloReporte, pagesize=A4, topMargin=12) alineacionTitulo = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=20, leading=40) alineacionTituloTabla = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=14, leading=40) alineacionOpTable = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=12, leading=40) alineacionResultados = ParagraphStyle(name="centrar", alignment=TA_LEFT, fontSize=12, leading=30) alineacionRestr = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=12, leading=30) story = [] restriccionesGuardadas = self.guardarRestricciones() resultados = self.guardarResultados() self.guardarRestricciones( ) # guarda solucion optima y el resultados de las variables story.append( Paragraph("Reporte generado por calculadora Método Simplex", alineacionTitulo)) story.append( Paragraph( f"Función Objetivo: {self.etiquetaFuncionObjetivo.text()}", alineacionResultados)) story.append(Paragraph(f"S.R:", alineacionResultados)) for restr in range(len(restriccionesGuardadas)): story.append( Paragraph(restriccionesGuardadas[restr], alineacionResultados)) for table in range(len(self.allTable)): self.arrayFila = [] for f in range(fila): item = self.allTable[table][f] self.arrayFila.append(item) tabla = Table(self.arrayFila, colWidths=50, rowHeights=40) tabla.setStyle([('GRID', (0, 0), (-1, -1), 2, colors.black), ('BOX', (0, 0), (-1, -1), 2, colors.black), ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ('BACKGROUND', (0, 0), (-1, 1), colors.HexColor('#572364')), ('TEXTCOLOR', (0, 0), (-1, 1), colors.HexColor('#ffffff'))]) story.append( Paragraph(f"Iteración #{table}", alineacionTituloTabla)) story.append(tabla) story.append(Spacer(0, 2)) if (table + 1 == len(self.allTable)): story.append(Spacer(0, 0)) else: story.append(Spacer(0, 250)) solucion = "La solución óptima es Z = " + self.solucion_optima story.append(Paragraph(solucion, alineacionTituloTabla)) variables = "" for iResul in range(len(resultados)): variables += resultados[iResul] story.append(Paragraph(variables, alineacionOpTable)) doc.build(story) msjErr = "Reporte generado. El pdf se abrirá automaticamente" msgBox5 = QMessageBox() msgBox5.setText(msjErr) msgBox5.setWindowTitle("Éxito") msgBox5.setStyleSheet( "font-size: 14px; font-weight: bold; font-family: Century Gothic" ) msgBox5.exec_() os.system(tituloReporte + "&& exit") except PermissionError: msjErr = "Ocurrió un error al generar el reporte" msgBox6 = QMessageBox() msgBox6.setText(msjErr) msgBox6.setWindowTitle("Error") msgBox6.setStyleSheet( "font-size: 14px; font-weight: bold; font-family: Century Gothic" ) msgBox6.exec_() def guardarResultados(self): resultados = [] columnas = self.columSRcompletas + 2 filas = self.numRestricciones + 4 arregloXBFila = [" "] * (columnas - 3) arregloXBCol = [" "] * self.numRestricciones for i in range(0, len(arregloXBFila), 1): arregloXBFila[i] = self.tablaU.item( 1, (i + 2)).text() # guardo XB Fila for i in range(0, len(arregloXBCol), 1): arregloXBCol[i] = self.tablaU.item((i + 2), 1).text() # guardo XB columna resultados = [" "] * len(arregloXBFila) # ciclo para llenar el arreglo de resultado for i in range(0, len(arregloXBFila), 1): resultados[i] = arregloXBFila[i] + " = 0, " # ciclo para asignar el valor de BI for j in range(0, len(arregloXBCol), 1): if arregloXBFila[i] == arregloXBCol[j]: resultados[ i] = arregloXBFila[i] + " = " + self.tablaU.item( (j + 2), (columnas - 1)).text() + ", " return resultados def validarTablaFuncion(self): datosOk = True for i in range(self.numVariables): try: dato = int(self.tablaVariables.item(0, i).text()) except ValueError: try: dato = float(self.tablaVariables.item(0, i).text()) except ValueError: datosOk = False self.show_popup_Informacion( "Dato no válido en la tabla Función Objetivo", "Solo se permite el ingreso de enteros o decimales") break except AttributeError: datosOk = False self.show_popup_Informacion( "Dato inválido", "Dato vacío en la tabla Función Objetivo") break return datosOk def validarTablaRestricciones(self): datosOk = True for row in range(self.tablaRestricciones.rowCount()): for col in range(self.tablaRestricciones.columnCount()): if not col == self.tablaRestricciones.columnCount( ) - 2: #no se toma en cuenta la columna con el signo de la restriccion try: dato = int( self.tablaRestricciones.item(row, col).text()) except ValueError: try: dato = float( self.tablaRestricciones.item(row, col).text()) except ValueError: datosOk = False self.show_popup_Informacion( "Dato no válido en la tabla Restricciones", "Solo se permite el ingreso de enteros o decimales" ) break except AttributeError: datosOk = False self.show_popup_Informacion( "Dato inválido", "Dato vacío en la tabla Restricciones") break if datosOk == False: break return datosOk
class FindAnnotationsDialog(SizePersistedDialog, Logger): GENERIC_STYLE = 'Any style' GENERIC_READER = 'Any reader' def __init__(self, opts): self.matched_ids = set() self.opts = opts self.prefs = opts.prefs super(FindAnnotationsDialog, self).__init__(self.opts.gui, 'find_annotations_dialog') self.setWindowTitle(_('Find Annotations')) self.setWindowIcon(self.opts.icon) self.l = QVBoxLayout(self) self.setLayout(self.l) self.search_criteria_gb = QGroupBox(self) self.search_criteria_gb.setTitle(_("Search criteria")) self.scgl = QGridLayout(self.search_criteria_gb) self.l.addWidget(self.search_criteria_gb) # addWidget(widget, row, col, rowspan, colspan) row = 0 # ~~~~~~~~ Create the Readers comboBox ~~~~~~~~ self.reader_label = QLabel(_('Reader')) self.reader_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.reader_label, row, 0, 1, 1) self.find_annotations_reader_comboBox = QComboBox() self.find_annotations_reader_comboBox.setObjectName('find_annotations_reader_comboBox') self.find_annotations_reader_comboBox.setToolTip(_('Reader annotations to search for')) self.find_annotations_reader_comboBox.addItem(self.GENERIC_READER) racs = ReaderApp.get_reader_app_classes() for ra in sorted(racs.keys()): self.find_annotations_reader_comboBox.addItem(ra) self.scgl.addWidget(self.find_annotations_reader_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Styles comboBox ~~~~~~~~ self.style_label = QLabel(_('Style')) self.style_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.style_label, row, 0, 1, 1) self.find_annotations_color_comboBox = QComboBox() self.find_annotations_color_comboBox.setObjectName('find_annotations_color_comboBox') self.find_annotations_color_comboBox.setToolTip(_('Annotation style to search for')) self.find_annotations_color_comboBox.addItem(self.GENERIC_STYLE) all_colors = COLOR_MAP.keys() all_colors.remove('Default') for color in sorted(all_colors): self.find_annotations_color_comboBox.addItem(color) self.scgl.addWidget(self.find_annotations_color_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Text LineEdit control ~~~~~~~~ self.text_label = QLabel(_('Text')) self.text_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.text_label, row, 0, 1, 1) self.find_annotations_text_lineEdit = MyLineEdit() self.find_annotations_text_lineEdit.setObjectName('find_annotations_text_lineEdit') self.scgl.addWidget(self.find_annotations_text_lineEdit, row, 1, 1, 3) self.reset_text_tb = QToolButton() self.reset_text_tb.setObjectName('reset_text_tb') self.reset_text_tb.setToolTip(_('Clear search criteria')) self.reset_text_tb.setIcon(QIcon(I('trash.png'))) self.reset_text_tb.clicked.connect(self.clear_text_field) self.scgl.addWidget(self.reset_text_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Note LineEdit control ~~~~~~~~ self.note_label = QLabel(_('Note')) self.note_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.note_label, row, 0, 1, 1) self.find_annotations_note_lineEdit = MyLineEdit() self.find_annotations_note_lineEdit.setObjectName('find_annotations_note_lineEdit') self.scgl.addWidget(self.find_annotations_note_lineEdit, row, 1, 1, 3) self.reset_note_tb = QToolButton() self.reset_note_tb.setObjectName('reset_note_tb') self.reset_note_tb.setToolTip(_('Clear search criteria')) self.reset_note_tb.setIcon(QIcon(I('trash.png'))) self.reset_note_tb.clicked.connect(self.clear_note_field) self.scgl.addWidget(self.reset_note_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Date range controls ~~~~~~~~ self.date_range_label = QLabel(_('Date range')) self.date_range_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.date_range_label, row, 0, 1, 1) # Date 'From' self.find_annotations_date_from_dateEdit = MyDateEdit(self, datetime(1970,1,1)) self.find_annotations_date_from_dateEdit.setObjectName('find_annotations_date_from_dateEdit') #self.find_annotations_date_from_dateEdit.current_val = datetime(1970,1,1) self.find_annotations_date_from_dateEdit.clear_button.clicked.connect(self.find_annotations_date_from_dateEdit.reset_from_date) self.scgl.addWidget(self.find_annotations_date_from_dateEdit, row, 1, 1, 1) self.scgl.addWidget(self.find_annotations_date_from_dateEdit.clear_button, row, 2, 1, 1) # Date 'To' self.find_annotations_date_to_dateEdit = MyDateEdit(self, datetime.today()) self.find_annotations_date_to_dateEdit.setObjectName('find_annotations_date_to_dateEdit') #self.find_annotations_date_to_dateEdit.current_val = datetime.today() self.find_annotations_date_to_dateEdit.clear_button.clicked.connect(self.find_annotations_date_to_dateEdit.reset_to_date) self.scgl.addWidget(self.find_annotations_date_to_dateEdit, row, 3, 1, 1) self.scgl.addWidget(self.find_annotations_date_to_dateEdit.clear_button, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create a horizontal line ~~~~~~~~ self.hl = QFrame(self) self.hl.setGeometry(QRect(0, 0, 1, 3)) self.hl.setFrameShape(QFrame.HLine) self.hl.setFrameShadow(QFrame.Raised) self.scgl.addWidget(self.hl, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the results label field ~~~~~~~~ self.result_label = QLabel('<p style="color:red">{0}</p>'.format(_('scanning…'))) self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setWordWrap(False) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.result_label.sizePolicy().hasHeightForWidth()) self.result_label.setSizePolicy(sizePolicy) self.result_label.setMinimumSize(QtCore.QSize(250, 0)) self.scgl.addWidget(self.result_label, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the ButtonBox ~~~~~~~~ self.dialogButtonBox = QDialogButtonBox(self) self.dialogButtonBox.setOrientation(Qt.Horizontal) if False: self.update_button = QPushButton(_('Update results')) self.update_button.setDefault(True) self.update_button.setVisible(False) self.dialogButtonBox.addButton(self.update_button, QDialogButtonBox.ActionRole) self.cancel_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Cancel) self.find_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Ok) self.find_button.setText(_('Find Matching Books')) self.l.addWidget(self.dialogButtonBox) self.dialogButtonBox.clicked.connect(self.find_annotations_dialog_clicked) # ~~~~~~~~ Add a spacer ~~~~~~~~ self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.l.addItem(self.spacerItem) # ~~~~~~~~ Restore previously saved settings ~~~~~~~~ self.restore_settings() # ~~~~~~~~ Declare sizing ~~~~~~~~ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.resize_dialog() # ~~~~~~~~ Connect all signals ~~~~~~~~ self.find_annotations_reader_comboBox.currentIndexChanged.connect(partial(self.update_results, 'reader')) self.find_annotations_color_comboBox.currentIndexChanged.connect(partial(self.update_results, 'color')) self.find_annotations_text_lineEdit.editingFinished.connect(partial(self.update_results, 'text')) self.find_annotations_note_lineEdit.editingFinished.connect(partial(self.update_results, 'note')) # self.connect(self.find_annotations_text_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_text_lineEdit.return_pressed.connect(self.return_pressed) # self.connect(self.find_annotations_note_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_note_lineEdit.return_pressed.connect(self.return_pressed) # Date range signals connected in inventory_available() # ~~~~~~~~ Allow dialog to render before doing inventory ~~~~~~~~ #field = self.prefs.get('cfg_annotations_destination_field', None) field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.opts.gui, field, get_date_range=True) self.annotated_books_scanner.signal.connect(self.inventory_available) QTimer.singleShot(1, self.start_inventory_scan) def clear_note_field(self): if str(self.find_annotations_note_lineEdit.text()) > '': self.find_annotations_note_lineEdit.setText('') self.update_results('clear_note_field') def clear_text_field(self): if str(self.find_annotations_text_lineEdit.text()) > '': self.find_annotations_text_lineEdit.setText('') self.update_results('clear_text_field') def find_annotations_dialog_clicked(self, button): if self.dialogButtonBox.buttonRole(button) == QDialogButtonBox.AcceptRole: self.save_settings() self.accept() elif self.dialogButtonBox.buttonRole(button) == QDialogButtonBox.RejectRole: self.close() def inventory_available(self): ''' Update the Date range widgets with the rounded oldest, newest dates Don't connect date signals until date range available ''' self._log_location() # Reset the date range based on available annotations oldest = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.oldest_annotation)) oldest_day = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.oldest_annotation).replace(hour=0, minute=0, second=0)) newest = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.newest_annotation)) newest_day = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.newest_annotation).replace(hour=23, minute=59, second=59)) # Set 'From' date limits to inventory values self.find_annotations_date_from_dateEdit.setMinimumDateTime(oldest_day) self.find_annotations_date_from_dateEdit.current_val = oldest self.find_annotations_date_from_dateEdit.setMaximumDateTime(newest_day) # Set 'To' date limits to inventory values self.find_annotations_date_to_dateEdit.setMinimumDateTime(oldest_day) self.find_annotations_date_to_dateEdit.current_val = newest_day self.find_annotations_date_to_dateEdit.setMaximumDateTime(newest_day) # Connect the signals for date range changes self.find_annotations_date_from_dateEdit.dateTimeChanged.connect(partial(self.update_results, 'from_date')) self.find_annotations_date_to_dateEdit.dateTimeChanged.connect(partial(self.update_results, 'to_date')) self.update_results('inventory_available') def restore_settings(self): self.blockSignals(True) ra = self.prefs.get('find_annotations_reader_comboBox', self.GENERIC_READER) ra_index = self.find_annotations_reader_comboBox.findText(ra) self.find_annotations_reader_comboBox.setCurrentIndex(ra_index) color = self.prefs.get('find_annotations_color_comboBox', self.GENERIC_STYLE) color_index = self.find_annotations_color_comboBox.findText(color) self.find_annotations_color_comboBox.setCurrentIndex(color_index) text = self.prefs.get('find_annotations_text_lineEdit', '') self.find_annotations_text_lineEdit.setText(text) note = self.prefs.get('find_annotations_note_lineEdit', '') self.find_annotations_note_lineEdit.setText(note) if False: from_date = self.prefs.get('find_annotations_date_from_dateEdit', datetime(1970,1,1)) self.find_annotations_date_from_dateEdit.current_val = from_date to_date = self.prefs.get('find_annotations_date_to_dateEdit', datetime.today()) self.find_annotations_date_to_dateEdit.current_val = to_date self.blockSignals(False) def return_pressed(self): self.update_results("return_pressed") def save_settings(self): ra = str(self.find_annotations_reader_comboBox.currentText()) self.prefs.set('find_annotations_reader_comboBox', ra) color = str(self.find_annotations_color_comboBox.currentText()) self.prefs.set('find_annotations_color_comboBox', color) text = str(self.find_annotations_text_lineEdit.text()) self.prefs.set('find_annotations_text_lineEdit', text) note = str(self.find_annotations_note_lineEdit.text()) self.prefs.set('find_annotations_note_lineEdit', note) if False: from_date = self.find_annotations_date_from_dateEdit.current_val self.prefs.set('find_annotations_date_from_dateEdit', from_date) to_date = self.find_annotations_date_to_dateEdit.current_val self.prefs.set('find_annotations_date_to_dateEdit', to_date) def start_inventory_scan(self): self._log_location() self.annotated_books_scanner.start() def update_results(self, trigger): #self._log_location(trigger) reader_to_match = str(self.find_annotations_reader_comboBox.currentText()) color_to_match = str(self.find_annotations_color_comboBox.currentText()) text_to_match = str(self.find_annotations_text_lineEdit.text()) note_to_match = str(self.find_annotations_note_lineEdit.text()) from_date = self.find_annotations_date_from_dateEdit.dateTime().toTime_t() to_date = self.find_annotations_date_to_dateEdit.dateTime().toTime_t() annotation_map = self.annotated_books_scanner.annotation_map #field = self.prefs.get("cfg_annotations_destination_field", None) field = get_cc_mapping('annotations', 'field', None) db = self.opts.gui.current_db matched_titles = [] self.matched_ids = set() for cid in annotation_map: mi = db.get_metadata(cid, index_is_id=True) soup = None if field == 'Comments': if mi.comments: soup = BeautifulSoup(mi.comments) else: if mi.get_user_metadata(field, False)['#value#'] is not None: soup = BeautifulSoup(mi.get_user_metadata(field, False)['#value#']) if soup: uas = soup.findAll('div', 'annotation') for ua in uas: # Are we already logged? if cid in self.matched_ids: continue # Check reader if reader_to_match != self.GENERIC_READER: this_reader = ua['reader'] if this_reader != reader_to_match: continue # Check color if color_to_match != self.GENERIC_STYLE: this_color = ua.find('table')['color'] if this_color != color_to_match: continue # Check date range, allow for mangled timestamp try: timestamp = float(ua.find('td', 'timestamp')['uts']) if timestamp < from_date or timestamp > to_date: continue except: continue highlight_text = '' try: pels = ua.findAll('p', 'highlight') highlight_text = '\n'.join([p.string for p in pels]) except: pass if text_to_match > '': if not re.search(text_to_match, highlight_text, flags=re.IGNORECASE): continue note_text = '' try: nels = ua.findAll('p', 'note') note_text = '\n'.join([n.string for n in nels]) except: pass if note_to_match > '': if not re.search(note_to_match, note_text, flags=re.IGNORECASE): continue # If we made it this far, add the id to matched_ids self.matched_ids.add(cid) matched_titles.append(mi.title) # Update the results box matched_titles.sort() if len(annotation_map): if len(matched_titles): first_match = ("<i>%s</i>" % matched_titles[0]) if len(matched_titles) == 1: results = first_match else: results = first_match + (_(" and {0} more.").format(len(matched_titles) - 1)) self.result_label.setText('<p style="color:blue">{0}</p>'.format(results)) else: self.result_label.setText('<p style="color:red">{0}</p>'.format(_('no matches'))) else: self.result_label.setText('<p style="color:red">{0}</p>'.format(_('no annotated books in library'))) self.resize_dialog()
class CustomColumnsTab(QWidget): def __init__(self, parent_dialog, plugin_action): self.parent_dialog = parent_dialog self.plugin_action = plugin_action QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) label = QLabel( _("If you have custom columns defined, they will be listed below. Choose if you would like these columns copied to new split books." )) label.setWordWrap(True) self.l.addWidget(label) self.l.addSpacing(5) scrollable = QScrollArea() scrollcontent = QWidget() scrollable.setWidget(scrollcontent) scrollable.setWidgetResizable(True) self.l.addWidget(scrollable) self.sl = QVBoxLayout() scrollcontent.setLayout(self.sl) self.custcol_checkboxes = {} custom_columns = self.plugin_action.gui.library_view.model( ).custom_columns for key, column in custom_columns.iteritems(): # print("\n============== %s ===========\n"%key) # for (k,v) in column.iteritems(): # print("column['%s'] => %s"%(k,v)) checkbox = QCheckBox('%s(%s)' % (column['name'], key)) checkbox.setToolTip( _("Copy this %s column to new split books...") % column['datatype']) checkbox.setChecked(key in prefs['custom_cols'] and prefs['custom_cols'][key]) self.custcol_checkboxes[key] = checkbox self.sl.addWidget(checkbox) self.sl.insertStretch(-1) self.l.addSpacing(5) label = QLabel(_("Source column:")) label.setToolTip( _("If set, the column below will be populated with the template below to record the source of the split file." )) label.setWordWrap(True) self.l.addWidget(label) horz = QHBoxLayout() self.sourcecol = QComboBox(self) self.sourcecol.setToolTip( _("Choose a column to populate with template on split.")) self.sourcecol.addItem('', 'none') for key, column in custom_columns.iteritems(): if column['datatype'] in ('text', 'comments'): self.sourcecol.addItem(column['name'], key) self.sourcecol.setCurrentIndex( self.sourcecol.findData(prefs['sourcecol'])) horz.addWidget(self.sourcecol) self.sourcetemplate = QLineEdit(self) self.sourcetemplate.setToolTip( _("Template from source book. Example: {title} by {authors}")) # if 'sourcetemplate' in prefs: self.sourcetemplate.setText(prefs['sourcetemplate']) # else: # self.sourcetemplate.setText("{title} by {authors}") horz.addWidget(self.sourcetemplate) self.l.addLayout(horz)
class HotkeyWidget(QWidget): def __init__(self, prefs, configName, title): QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) self.configName = configName self.hotkeyLayout = QHBoxLayout() self.l.addLayout(self.hotkeyLayout) enabledLabel = QLabel(title) self.hotkeyLayout.addWidget(enabledLabel) self.enabledBox = QCheckBox() self.hotkeyLayout.addWidget(self.enabledBox) self.enabledBox.setChecked(prefs[configName + '_hotkey_enabled']) hotkeyLayout2 = QHBoxLayout() self.l.addLayout(hotkeyLayout2) ctrlLabel = QLabel("Ctrl") self.ctrlBox = QCheckBox() self.ctrlBox.setChecked(prefs[configName + '_hotkey_ctrl']) ctrlLabel.setBuddy(self.ctrlBox) hotkeyLayout2.addWidget(ctrlLabel) hotkeyLayout2.addWidget(self.ctrlBox) altLabel = QLabel("Alt") self.altBox = QCheckBox() self.altBox.setChecked(prefs[configName + '_hotkey_alt']) altLabel.setBuddy(self.altBox) hotkeyLayout2.addWidget(altLabel) hotkeyLayout2.addWidget(self.altBox) shiftLabel = QLabel("Shift") self.shiftBox = QCheckBox() self.shiftBox.setChecked(prefs[configName + '_hotkey_shift']) shiftLabel.setBuddy(self.shiftBox) hotkeyLayout2.addWidget(shiftLabel) hotkeyLayout2.addWidget(self.shiftBox) self.keycodeBox = QComboBox() for key, value in keycodes.iteritems(): self.keycodeBox.addItem(key, value) index = self.keycodeBox.findData(prefs[configName + '_hotkey_keycode']) if index != -1: self.keycodeBox.setCurrentIndex(index) hotkeyLayout2.addWidget(self.keycodeBox) def save_settings(self, prefs): prefs[self.configName + '_hotkey_enabled'] = self.enabledBox.isChecked() prefs[self.configName + '_hotkey_ctrl'] = self.ctrlBox.isChecked() prefs[self.configName + '_hotkey_alt'] = self.altBox.isChecked() prefs[self.configName + '_hotkey_shift'] = self.shiftBox.isChecked() prefs[self.configName + '_hotkey_keycode'] = keycodes[unicode(self.keycodeBox.currentText())]
class RuleEditor(QDialog): # {{{ @property def doing_multiple(self): return hasattr(self, 'multiple_icon_cb') and self.multiple_icon_cb.isChecked() def __init__(self, fm, pref_name, parent=None): QDialog.__init__(self, parent) self.fm = fm if pref_name == 'column_color_rules': self.rule_kind = 'color' rule_text = _('column coloring') elif pref_name == 'column_icon_rules': self.rule_kind = 'icon' rule_text = _('column icon') elif pref_name == 'cover_grid_icon_rules': self.rule_kind = 'emblem' rule_text = _('Cover grid emblem') self.setWindowIcon(QIcon(I('format-fill-color.png'))) self.setWindowTitle(_('Create/edit a {0} rule').format(rule_text)) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel(_('Create a {0} rule by' ' filling in the boxes below').format(rule_text)) l.addWidget(l1, 0, 0, 1, 8) self.f1 = QFrame(self) self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 8) self.l2 = l2 = QLabel(_('Add the emblem:') if self.rule_kind == 'emblem' else _('Set the')) l.addWidget(l2, 2, 0) if self.rule_kind == 'color': l.addWidget(QLabel(_('color'))) elif self.rule_kind == 'icon': self.kind_box = QComboBox(self) for tt, t in icon_rule_kinds: self.kind_box.addItem(tt, t) l.addWidget(self.kind_box, 2, 1) self.kind_box.setToolTip(textwrap.fill(_( 'If you choose composed icons and multiple rules match, then all the' ' matching icons will be combined, otherwise the icon from the' ' first rule to match will be used.'))) else: pass self.l3 = l3 = QLabel(_('of the column:')) l.addWidget(l3, 2, 2) self.column_box = QComboBox(self) l.addWidget(self.column_box, 2, 3) self.l4 = l4 = QLabel(_('to')) l.addWidget(l4, 2, 4) if self.rule_kind == 'emblem': l3.setVisible(False), self.column_box.setVisible(False), l4.setVisible(False) def create_filename_box(): self.filename_box = f = QComboBox() self.filenamebox_view = v = QListView() v.setIconSize(QSize(32, 32)) self.filename_box.setView(v) self.orig_filenamebox_view = f.view() f.setMinimumContentsLength(20), f.setSizeAdjustPolicy(f.AdjustToMinimumContentsLengthWithIcon) self.populate_icon_filenames() if self.rule_kind == 'color': self.color_box = ColorButton(parent=self) self.color_label = QLabel('Sample text Sample text') self.color_label.setTextFormat(Qt.RichText) l.addWidget(self.color_box, 2, 5) l.addWidget(self.color_label, 2, 6) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) elif self.rule_kind == 'emblem': create_filename_box() self.update_filename_box() self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add new image')) l.addWidget(self.filename_box) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('(Images should be square-ish)')), 2, 7) l.setColumnStretch(7, 10) else: create_filename_box() vb = QVBoxLayout() self.multiple_icon_cb = QCheckBox(_('Choose &more than one icon')) vb.addWidget(self.multiple_icon_cb) self.update_filename_box() self.multiple_icon_cb.clicked.connect(self.multiple_box_clicked) vb.addWidget(self.filename_box) l.addLayout(vb, 2, 5) self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add icon')) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('Icons should be square or landscape')), 2, 7) l.setColumnStretch(7, 10) self.l5 = l5 = QLabel( _('Only if the following conditions are all satisfied:')) l.addWidget(l5, 3, 0, 1, 7) self.scroll_area = sa = QScrollArea(self) sa.setMinimumHeight(300) sa.setMinimumWidth(950) sa.setWidgetResizable(True) l.addWidget(sa, 4, 0, 1, 8) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add &another condition')) l.addWidget(b, 5, 0, 1, 8) b.clicked.connect(self.add_blank_condition) self.l6 = l6 = QLabel(_('You can disable a condition by' ' blanking all of its boxes')) l.addWidget(l6, 6, 0, 1, 8) self.bb = bb = QDialogButtonBox( QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 7, 0, 1, 8) if self.rule_kind != 'color': self.remove_button = b = bb.addButton(_('&Remove icon'), bb.ActionRole) b.setIcon(QIcon(I('minus.png'))) b.setMenu(QMenu()) b.setToolTip('<p>' + _('Remove a previously added icon. Note that doing so will cause rules that use it to stop working.')) self.update_remove_button() self.conditions_widget = QWidget(self) sa.setWidget(self.conditions_widget) self.conditions_widget.setLayout(QVBoxLayout()) self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions = [] if self.rule_kind == 'color': for b in (self.column_box, ): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) for key in sorted(displayable_columns(fm), key=lambda(k): sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and self.rule_kind != 'color': continue name = all_columns_string if key == color_row_key else fm[key]['name'] if name: self.column_box.addItem(name, key) self.column_box.setCurrentIndex(0) if self.rule_kind == 'color': self.color_box.color = '#000' self.update_color_label() self.color_box.color_changed.connect(self.update_color_label) else: self.rule_icon_files = [] self.filename_button.clicked.connect(self.filename_button_clicked) self.resize(self.sizeHint()) def multiple_box_clicked(self): self.update_filename_box() self.update_icon_filenames_in_box() @property def icon_folder(self): return os.path.join(config_dir, 'cc_icons') def populate_icon_filenames(self): d = self.icon_folder self.icon_file_names = [] if os.path.exists(d): for icon_file in os.listdir(d): icon_file = lower(icon_file) if os.path.exists(os.path.join(d, icon_file)) and icon_file.endswith('.png'): self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) def update_filename_box(self): doing_multiple = self.doing_multiple model = QStandardItemModel() self.filename_box.setModel(model) self.icon_file_names.sort(key=sort_key) if doing_multiple: item = QStandardItem(_('Open to see checkboxes')) item.setIcon(QIcon(I('blank.png'))) else: item = QStandardItem('') item.setFlags(Qt.ItemFlag(0)) model.appendRow(item) for i,filename in enumerate(self.icon_file_names): item = QStandardItem(filename) if doing_multiple: item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(Qt.Unchecked, Qt.CheckStateRole) else: item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) icon = QIcon(os.path.join(self.icon_folder, filename)) item.setIcon(icon) model.appendRow(item) def update_color_label(self): pal = QApplication.palette() bg1 = unicode(pal.color(pal.Base).name()) bg2 = unicode(pal.color(pal.AlternateBase).name()) c = self.color_box.color self.color_label.setText(''' <span style="color: {c}; background-color: {bg1}"> {st} </span> <span style="color: {c}; background-color: {bg2}"> {st} </span> '''.format(c=c, bg1=bg1, bg2=bg2, st=_('Sample text'))) def sanitize_icon_file_name(self, icon_path): n = lower(sanitize_file_name_unicode( os.path.splitext( os.path.basename(icon_path))[0]+'.png')) return n.replace("'", '_') def filename_button_clicked(self): try: path = choose_files(self, 'choose_category_icon', _('Select Icon'), filters=[ (_('Images'), ['png', 'gif', 'jpg', 'jpeg'])], all_files=False, select_only_single_file=True) if path: icon_path = path[0] icon_name = self.sanitize_icon_file_name(icon_path) if icon_name not in self.icon_file_names: self.icon_file_names.append(icon_name) try: p = QIcon(icon_path).pixmap(QSize(128, 128)) d = self.icon_folder if not os.path.exists(os.path.join(d, icon_name)): if not os.path.exists(d): os.makedirs(d) with open(os.path.join(d, icon_name), 'wb') as f: f.write(pixmap_to_data(p, format='PNG')) except: import traceback traceback.print_exc() self.update_filename_box() self.update_remove_button() if self.doing_multiple: if icon_name not in self.rule_icon_files: self.rule_icon_files.append(icon_name) self.update_icon_filenames_in_box() else: self.filename_box.setCurrentIndex(self.filename_box.findText(icon_name)) self.filename_box.adjustSize() except: import traceback traceback.print_exc() return def get_filenames_from_box(self): if self.doing_multiple: model = self.filename_box.model() fnames = [] for i in range(1, model.rowCount()): item = model.item(i, 0) if item.checkState() == Qt.Checked: fnames.append(lower(unicode(item.text()))) fname = ' : '.join(fnames) else: fname = lower(unicode(self.filename_box.currentText())) return fname def update_icon_filenames_in_box(self): if self.rule_icon_files: if not self.doing_multiple: idx = self.filename_box.findText(self.rule_icon_files[0]) if idx >= 0: self.filename_box.setCurrentIndex(idx) else: self.filename_box.setCurrentIndex(0) else: model = self.filename_box.model() for icon in self.rule_icon_files: idx = self.filename_box.findText(icon) if idx >= 0: item = model.item(idx) item.setCheckState(Qt.Checked) def update_remove_button(self): m = self.remove_button.menu() m.clear() for name in self.icon_file_names: m.addAction(QIcon(os.path.join(self.icon_folder, name)), name).triggered.connect(partial( self.remove_image, name)) def remove_image(self, name): try: os.remove(os.path.join(self.icon_folder, name)) except EnvironmentError: pass else: self.populate_icon_filenames() self.update_remove_button() self.update_filename_box() self.update_icon_filenames_in_box() def add_blank_condition(self): c = ConditionEditor(self.fm, parent=self.conditions_widget) self.conditions.append(c) self.conditions_widget.layout().addWidget(c) def apply_rule(self, kind, col, rule): if kind == 'color': if rule.color: self.color_box.color = rule.color else: if self.rule_kind == 'icon': for i, tup in enumerate(icon_rule_kinds): if kind == tup[1]: self.kind_box.setCurrentIndex(i) break self.rule_icon_files = [ic.strip() for ic in rule.color.split(':')] if len(self.rule_icon_files) > 1: self.multiple_icon_cb.setChecked(True) self.update_filename_box() self.update_icon_filenames_in_box() for i in range(self.column_box.count()): c = unicode(self.column_box.itemData(i) or '') if col == c: self.column_box.setCurrentIndex(i) break for c in rule.conditions: ce = ConditionEditor(self.fm, parent=self.conditions_widget) self.conditions.append(ce) self.conditions_widget.layout().addWidget(ce) try: ce.condition = c except: import traceback traceback.print_exc() def accept(self): if self.rule_kind != 'color': fname = self.get_filenames_from_box() if not fname: error_dialog(self, _('No icon selected'), _('You must choose an icon for this rule'), show=True) return if self.validate(): QDialog.accept(self) def validate(self): r = Rule(self.fm) for c in self.conditions: condition = c.condition if condition is not None: try: r.add_condition(*condition) except Exception as e: import traceback error_dialog(self, _('Invalid condition'), _('One of the conditions for this rule is' ' invalid: <b>%s</b>')%e, det_msg=traceback.format_exc(), show=True) return False if len(r.conditions) < 1: error_dialog(self, _('No conditions'), _('You must specify at least one non-empty condition' ' for this rule'), show=True) return False return True @property def rule(self): r = Rule(self.fm) if self.rule_kind != 'color': r.color = self.get_filenames_from_box() else: r.color = self.color_box.color idx = self.column_box.currentIndex() col = unicode(self.column_box.itemData(idx) or '') for c in self.conditions: condition = c.condition if condition is not None: r.add_condition(*condition) if self.rule_kind == 'icon': kind = unicode(self.kind_box.itemData( self.kind_box.currentIndex()) or '') else: kind = self.rule_kind return kind, col, r
class EKWindow(QDialog): """ Class which is responisble for running this entire application """ def __init__(self): """ Constructor for this class """ super(EKWindow, self).__init__() self.engine = Engine("tables/Tamil-bamini.txt.in") # Settings file initialization self.settingsFilePath = os.getenv("APPDATA") + "\\" + qApp.applicationName() + "\eksettings.ini" self.init_settings() # Function to check whether the settings file is or not. self.iniSettings = QSettings(self.settingsFilePath, QSettings.IniFormat) # Variable Initialization self.registrySettings = QSettings("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", QSettings.NativeFormat) self.shortcutModifierKey = self.iniSettings.value("shortcut_modifier") self.shortcutKey = self.iniSettings.value("shortcut") self.selectedKeyboard = self.iniSettings.value("selected_keyboard") self.keyboardStatus = False self.fileName = "" # Ui variable Initialization self.iconGroupBox = QGroupBox("Keyboards") self.iconLabel = QLabel("Keyboard:") self.iconComboBox = QComboBox(self) self.shortcutGroupBox = QGroupBox("Shortcut Setting") self.shortcutComboBox1 = QComboBox(self) self.shortcutComboBox2 = QComboBox(self) self.otherSettingsGroupBox = QGroupBox("Other Settings") self.checkboxStartWithWindows = QCheckBox() self.minimizeAction = QAction("Minimize", self) self.maximizeAction = QAction("Maximize", self) self.settingsAction = QAction("Settings", self) self.aboutAction = QAction("About", self) self.quitAction = QAction("Quit", self) self.trayIconMenu = QMenu(self) self.trayIcon = QSystemTrayIcon(self) self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(self.iconGroupBox) self.mainLayout.addWidget(self.shortcutGroupBox) self.mainLayout.addWidget(self.otherSettingsGroupBox) self.setLayout(self.mainLayout) # UI constructor and connectors self.create_settings_group_boxes() self.create_actions() self.create_tray_icon() # Signal connectors self.iconComboBox.currentIndexChanged.connect(self.change_keyboard) self.shortcutComboBox1.currentIndexChanged.connect(self.set_shortcut_modifier) self.shortcutComboBox2.currentIndexChanged.connect(self.set_shortcut_key) self.trayIcon.activated.connect(self.icon_activated) self.checkboxStartWithWindows.stateChanged.connect(self.checkbox_start_with_windows_ticked) if self.keyboardStatus: self.iconComboBox.setCurrentIndex(self.selectedKeyBoard) else: self.change_keyboard(0) self.iconComboBox.setCurrentIndex(0) self.trayIcon.show() self.set_shortcut_key() self.setWindowTitle(qApp.applicationName() + " " + qApp.applicationVersion()) def init_settings(self): """ Function to check whether the settings file is there or not. If there is no file, then it will create with default settings. """ if not os.path.exists(self.settingsFilePath): settings_dir = os.getenv("APPDATA") + "\\" + qApp.applicationName() if not os.path.exists(settings_dir): os.makedirs(settings_dir) setting_path = "" if getattr(sys, 'frozen', False): setting_path = os.path.dirname(sys.executable) elif __file__: setting_path = os.path.dirname(__file__) shutil.copyfile(os.path.join(setting_path, "resources\eksettings.ini"), self.settingsFilePath) return def create_settings_group_boxes(self): """ UI generator function. """ self.iconComboBox.addItem("No Keyboard") self.iconComboBox.addItem("Tamil99") self.iconComboBox.addItem("Phonetic") self.iconComboBox.addItem("Typewriter") self.iconComboBox.addItem("Bamini") self.iconComboBox.addItem("Inscript") icon_layout = QHBoxLayout(self) icon_layout.addWidget(self.iconLabel) icon_layout.addWidget(self.iconComboBox) icon_layout.addStretch() self.iconGroupBox.setLayout(icon_layout) shortcut_label_1 = QLabel("Modifier Key:") shortcut_label_2 = QLabel("Shortcut Key:") self.shortcutComboBox1.addItem("NONE") self.shortcutComboBox1.addItem("CTRL") self.shortcutComboBox1.addItem("ALT") modifier_index = self.shortcutComboBox1.findText(self.shortcutModifierKey) self.shortcutComboBox1.setCurrentIndex(modifier_index) self.shortcutComboBox2.setMinimumContentsLength(3) if modifier_index == 0: self.shortcutComboBox2.addItem("F1") self.shortcutComboBox2.addItem("ESC") self.shortcutComboBox2.addItem("F2") self.shortcutComboBox2.addItem("F3") self.shortcutComboBox2.addItem("F4") self.shortcutComboBox2.addItem("F5") self.shortcutComboBox2.addItem("F6") self.shortcutComboBox2.addItem("F7") self.shortcutComboBox2.addItem("F8") self.shortcutComboBox2.addItem("F9") self.shortcutComboBox2.addItem("F10") else: self.shortcutComboBox2.addItem("1") self.shortcutComboBox2.addItem("2") self.shortcutComboBox2.addItem("3") self.shortcutComboBox2.addItem("4") self.shortcutComboBox2.addItem("5") self.shortcutComboBox2.addItem("6") self.shortcutComboBox2.addItem("7") self.shortcutComboBox2.addItem("8") self.shortcutComboBox2.addItem("9") self.shortcutComboBox2.addItem("0") key_index = self.shortcutComboBox2.findText(self.shortcutKey) self.shortcutComboBox2.setCurrentIndex(key_index) shortcut_layout = QHBoxLayout(self) shortcut_layout.addWidget(shortcut_label_1) shortcut_layout.addWidget(self.shortcutComboBox1) shortcut_layout.addWidget(shortcut_label_2) shortcut_layout.addWidget(self.shortcutComboBox2) shortcut_layout.addStretch() self.shortcutGroupBox.setLayout(shortcut_layout) checkbox_start_with_windows_label = QLabel("Start eKalappai whenever windows starts") # if registry entry for auto start with windows for the current user exists, then check the checkbox if self.registrySettings.contains(qApp.applicationName()): self.checkboxStartWithWindows.setChecked(True) else: self.checkboxStartWithWindows.setChecked(False) other_settings_layout = QHBoxLayout(self) other_settings_layout.addWidget(checkbox_start_with_windows_label) other_settings_layout.addWidget(self.checkboxStartWithWindows) other_settings_layout.addStretch() self.otherSettingsGroupBox.setLayout(other_settings_layout) def set_shortcut_key(self): """ Function to change the shortcut key when its changed. """ self.shortcutKey = self.shortcutComboBox2.currentText() self.iniSettings.setValue("shortcut", self.shortcutKey) self.register_shortcut_listener() if self.shortcutKey == "ESC": self.shortcutKeyHex = 0x1B elif self.shortcutKey == "F1": self.shortcutKeyHex = 0x70 elif self.shortcutKey == "F2": self.shortcutKeyHex = 0x71 elif self.shortcutKey == "F3": self.shortcutKeyHex = 0x72 elif self.shortcutKey == "F4": self.shortcutKeyHex = 0x73 elif self.shortcutKey == "F5": self.shortcutKeyHex = 0x74 elif self.shortcutKey == "F6": self.shortcutKeyHex = 0x75 elif self.shortcutKey == "F7": self.shortcutKeyHex = 0x76 elif self.shortcutKey == "F8": self.shortcutKeyHex = 0x77 elif self.shortcutKey == "F9": self.shortcutKeyHex = 0x78 elif self.shortcutKey == "F10": self.shortcutKeyHex = 0x79 elif self.shortcutKey == "1": self.shortcutKeyHex = 0x31 elif self.shortcutKey == "2": self.shortcutKeyHex = 0x32 elif self.shortcutKey == "3": self.shortcutKeyHex = 0x33 elif self.shortcutKey == "4": self.shortcutKeyHex = 0x34 elif self.shortcutKey == "5": self.shortcutKeyHex = 0x35 elif self.shortcutKey == "6": self.shortcutKeyHex = 0x36 elif self.shortcutKey == "7": self.shortcutKeyHex = 0x37 elif self.shortcutKey == "8": self.shortcutKeyHex = 0x38 elif self.shortcutKey == "9": self.shortcutKeyHex = 0x39 elif self.shortcutKey == "0": self.shortcutKeyHex = 0x30 def create_actions(self): """ Slot connectors for all right clicking and other actions. """ self.minimizeAction.triggered.connect(self.hide) self.maximizeAction.triggered.connect(self.showMaximized) self.settingsAction.triggered.connect(self.showNormal) self.aboutAction.triggered.connect(self.show_about) self.quitAction.triggered.connect(self.quit) def quit(self): self.engine.un_hook() exit(0) def create_tray_icon(self): """ Tray icon creator and corresponding connectors """ self.trayIconMenu.addAction(self.settingsAction) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.aboutAction) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.quitAction) self.trayIcon.setContextMenu(self.trayIconMenu) def setVisible(self, visible): self.settingsAction.setEnabled(self.isMaximized() or not visible) super(EKWindow, self).setVisible(visible) def closeEvent(self, event): if self.trayIcon.isVisible(): self.hide() event.ignore() def load_keyboard(self): """ Mapping file loading function """ if self.selectedKeyboard == 1: self.fileName = "tables/Tamil-tamil99.txt.in" elif self.selectedKeyboard == 2: self.fileName = "tables/Tamil-phonetic.txt.in" elif self.selectedKeyboard == 3: self.fileName = "tables/Tamil-typewriter.txt.in" elif self.selectedKeyboard == 4: self.fileName = "tables/Tamil-bamini.txt.in" elif self.selectedKeyboard == 5: self.fileName = "tables/Tamil-inscript.txt.in" else: pass def getPath(self, index): if index == 1: self.path = "tables/Tamil-tamil99.txt.in" elif index == 2: self.path = "tables/Tamil-phonetic.txt.in" elif index == 3: self.path = "tables/Tamil-typewriter.txt.in" elif index == 4: self.path = "tables/Tamil-bamini.txt.in" elif index == 5: self.path = "tables/Tamil-inscript.txt.in" else: pass def change_keyboard(self, index): """ Function to change the keyboard based on the index which was sent as a param """ if int(index) != 0: self.iniSettings.setValue("selected_keyboard", index) self.selectedKeyboard = index self.iconComboBox.setCurrentIndex(int(index)) icon = self.iconComboBox.itemIcon(int(index)) self.trayIcon.setIcon(icon) self.setWindowIcon(icon) self.trayIcon.setToolTip(self.iconComboBox.itemText(int(index))) self.show_tray_message(index) self.load_keyboard() if int(index) != 0: self.getPath(int(index)) self.engine.file_name = self.path self.engine.initialize() self.engine.conv_state = True else: try: self.engine.conv_state = False except: pass def icon_activated(self, reason): """ Function to toggle the state when the icon is clicked or shortcut key is pressed """ if reason == QSystemTrayIcon.DoubleClick: pass elif reason == QSystemTrayIcon.Trigger: if self.keyboardStatus: self.keyboardStatus = False else: self.keyboardStatus = True if self.keyboardStatus: self.change_keyboard(self.selectedKeyboard) else: self.change_keyboard(0) elif reason == QSystemTrayIcon.MiddleClick: pass else: pass def show_tray_message(self, index): """ Tray message generator when there is change in keyboard state """ icon = QSystemTrayIcon.MessageIcon(0) message = self.iconComboBox.itemText(int(index)) + " set" self.trayIcon.showMessage(qApp.applicationName() + " " + qApp.applicationVersion(), message, icon, 100) def checkbox_start_with_windows_ticked(self): """ Function to add or disable registry entry to auto start ekalappai with windows for the current users """ if self.checkboxStartWithWindows.isChecked(): self.registrySettings.setValue(qApp.applicationName(), qApp.applicationFilePath()) else: self.registrySettings.remove(qApp.applicationName()) def show_about(self): pass def set_shortcut_modifier(self, index): """ Function to set the shortcut modifier when its changed. """ self.iniSettings.setValue("shortcut_modifier", self.shortcutComboBox1.currentText()) self.shortcutModifierKey = self.iniSettings.value("shortcut_modifier") # if none is selected, the allowed single key shortcuts should change if index == 0: self.shortcutComboBox2.clear() self.shortcutComboBox2.addItem("ESC") self.shortcutComboBox2.addItem("F1") self.shortcutComboBox2.addItem("F2") self.shortcutComboBox2.addItem("F3") self.shortcutComboBox2.addItem("F4") self.shortcutComboBox2.addItem("F5") self.shortcutComboBox2.addItem("F6") self.shortcutComboBox2.addItem("F7") self.shortcutComboBox2.addItem("F8") self.shortcutComboBox2.addItem("F9") self.shortcutComboBox2.addItem("F10") else: self.shortcutComboBox2.clear() self.shortcutComboBox2.addItem("1") self.shortcutComboBox2.addItem("2") self.shortcutComboBox2.addItem("3") self.shortcutComboBox2.addItem("4") self.shortcutComboBox2.addItem("5") self.shortcutComboBox2.addItem("6") self.shortcutComboBox2.addItem("7") self.shortcutComboBox2.addItem("8") self.shortcutComboBox2.addItem("9") self.shortcutComboBox2.addItem("0") self.register_shortcut_listener() def register_shortcut_listener(self): self.engine.event_queue.remove_all() if self.iniSettings.value("shortcut_modifier") == "NONE": self.engine.event_queue.register_event([[self.shortcutKey], self.icon_activated, QSystemTrayIcon.Trigger]) elif self.iniSettings.value("shortcut_modifier") == "CTRL": self.engine.event_queue.register_event([['Lcontrol', self.shortcutKey], self.icon_activated, QSystemTrayIcon.Trigger]) self.engine.event_queue.register_event([['Rcontrol', self.shortcutKey], self.icon_activated, QSystemTrayIcon.Trigger]) elif self.iniSettings.value("shortcut_modifier") == "ALT": self.engine.event_queue.register_event([['LMenu', self.shortcutKey], self.icon_activated, QSystemTrayIcon.Trigger]) self.engine.event_queue.register_event([['RMenu', self.shortcutKey], self.icon_activated, QSystemTrayIcon.Trigger]) return True
class CreateVirtualLibrary(QDialog): # {{{ def __init__(self, gui, existing_names, editing=None): QDialog.__init__(self, gui) self.gui = gui self.existing_names = existing_names if editing: self.setWindowTitle(_('Edit virtual library')) else: self.setWindowTitle(_('Create virtual library')) self.setWindowIcon(QIcon(I('lt.png'))) gl = QGridLayout() self.setLayout(gl) self.la1 = la1 = QLabel(_('Virtual library &name:')) gl.addWidget(la1, 0, 0) self.vl_name = QComboBox() self.vl_name.setEditable(True) self.vl_name.lineEdit().setMaxLength(MAX_VIRTUAL_LIBRARY_NAME_LENGTH) la1.setBuddy(self.vl_name) gl.addWidget(self.vl_name, 0, 1) self.editing = editing self.saved_searches_label = sl = QTextBrowser(self) sl.viewport().setAutoFillBackground(False) gl.addWidget(sl, 2, 0, 1, 2) self.la2 = la2 = QLabel(_('&Search expression:')) gl.addWidget(la2, 1, 0) self.vl_text = QLineEdit() self.vl_text.textChanged.connect(self.search_text_changed) la2.setBuddy(self.vl_text) gl.addWidget(self.vl_text, 1, 1) self.vl_text.setText(_build_full_search_string(self.gui)) self.sl = sl = QLabel( '<p>' + _('Create a virtual library based on: ') + ('<a href="author.{0}">{0}</a>, ' '<a href="tag.{1}">{1}</a>, ' '<a href="publisher.{2}">{2}</a>, ' '<a href="series.{3}">{3}</a>, ' '<a href="search.{4}">{4}</a>.').format(_('Authors'), _( 'Tags'), _('Publishers'), _('Series'), _('Saved searches'))) sl.setWordWrap(True) sl.setTextInteractionFlags(Qt.LinksAccessibleByMouse) sl.linkActivated.connect(self.link_activated) gl.addWidget(sl, 3, 0, 1, 2) gl.setRowStretch(3, 10) self.hl = hl = QLabel( _(''' <h2>Virtual libraries</h2> <p>Using <i>virtual libraries</i> you can restrict calibre to only show you books that match a search. When a virtual library is in effect, calibre behaves as though the library contains only the matched books. The Tag browser display only the tags/authors/series/etc. that belong to the matched books and any searches you do will only search within the books in the virtual library. This is a good way to partition your large library into smaller and easier to work with subsets.</p> <p>For example you can use a Virtual library to only show you books with the Tag <i>"Unread"</i> or only books by <i>"My favorite author"</i> or only books in a particular series.</p> <p>More information and examples are available in the <a href="%s">User Manual</a>.</p> ''') % localize_user_manual_link( 'https://manual.calibre-ebook.com/virtual_libraries.html')) hl.setWordWrap(True) hl.setOpenExternalLinks(True) hl.setFrameStyle(hl.StyledPanel) gl.addWidget(hl, 0, 3, 4, 1) bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) gl.addWidget(bb, 4, 0, 1, 0) if editing: db = self.gui.current_db virt_libs = db.prefs.get('virtual_libraries', {}) for dex, vl in enumerate(sorted(virt_libs.keys(), key=sort_key)): self.vl_name.addItem(vl, virt_libs.get(vl, '')) if vl == editing: self.vl_name.setCurrentIndex(dex) self.original_index = dex self.original_search = virt_libs.get(editing, '') self.vl_text.setText(self.original_search) self.new_name = editing self.vl_name.currentIndexChanged[int].connect( self.name_index_changed) self.vl_name.lineEdit().textEdited.connect(self.name_text_edited) self.resize(self.sizeHint() + QSize(150, 25)) def search_text_changed(self, txt): db = self.gui.current_db searches = [_('Saved searches recognized in the expression:')] txt = unicode(txt) while txt: p = txt.partition('search:') if p[1]: # found 'search:' possible_search = p[2] if possible_search: # something follows the 'search:' if possible_search[0] == '"': # strip any quotes possible_search = possible_search[1:].partition('"') else: # find end of the search name. Is EOL, space, rparen sp = possible_search.find(' ') pp = possible_search.find(')') if pp < 0 or (sp > 0 and sp <= pp): # space in string before rparen, or neither found possible_search = possible_search.partition(' ') else: # rparen in string before space possible_search = possible_search.partition(')') txt = possible_search[2] # grab remainder of the string search_name = possible_search[0] if search_name.startswith('='): search_name = search_name[1:] if search_name in db.saved_search_names(): searches.append(search_name + '=' + db.saved_search_lookup(search_name)) else: txt = '' else: txt = '' if len(searches) > 1: self.saved_searches_label.setPlainText('\n'.join(searches)) else: self.saved_searches_label.setPlainText('') def name_text_edited(self, new_name): self.new_name = unicode(new_name) def name_index_changed(self, dex): if self.editing and (self.vl_text.text() != self.original_search or self.new_name != self.editing): if not question_dialog( self.gui, _('Search text changed'), _('The virtual library name or the search text has changed. ' 'Do you want to discard these changes?'), default_yes=False): self.vl_name.blockSignals(True) self.vl_name.setCurrentIndex(self.original_index) self.vl_name.lineEdit().setText(self.new_name) self.vl_name.blockSignals(False) return self.new_name = self.editing = self.vl_name.currentText() self.original_index = dex self.original_search = unicode(self.vl_name.itemData(dex) or '') self.vl_text.setText(self.original_search) def link_activated(self, url): db = self.gui.current_db f, txt = unicode(url).partition('.')[0::2] if f == 'search': names = db.saved_search_names() else: names = getattr(db, 'all_%s_names' % f)() d = SelectNames(names, txt, parent=self) if d.exec_() == d.Accepted: prefix = f + 's' if f in {'tag', 'author'} else f if f == 'search': search = [ '(%s)' % (db.saved_search_lookup(x)) for x in d.names ] else: search = [ '%s:"=%s"' % (prefix, x.replace('"', '\\"')) for x in d.names ] if search: if not self.editing: self.vl_name.lineEdit().setText(d.names.next()) self.vl_name.lineEdit().setCursorPosition(0) self.vl_text.setText(d.match_type.join(search)) self.vl_text.setCursorPosition(0) def accept(self): n = unicode(self.vl_name.currentText()).strip() if not n: error_dialog( self.gui, _('No name'), _('You must provide a name for the new virtual library'), show=True) return if n.startswith('*'): error_dialog(self.gui, _('Invalid name'), _('A virtual library name cannot begin with "*"'), show=True) return if n in self.existing_names and n != self.editing: if not question_dialog( self.gui, _('Name already in use'), _('That name is already in use. Do you want to replace it ' 'with the new search?'), default_yes=False): return v = unicode(self.vl_text.text()).strip() if not v: error_dialog( self.gui, _('No search string'), _('You must provide a search to define the new virtual library' ), show=True) return try: db = self.gui.library_view.model().db recs = db.data.search_getting_ids('', v, use_virtual_library=False, sort_results=False) except ParseException as e: error_dialog(self.gui, _('Invalid search'), _('The search in the search box is not valid'), det_msg=e.msg, show=True) return if not recs and not question_dialog( self.gui, _('Search found no books'), _('The search found no books, so the virtual library ' 'will be empty. Do you really want to use that search?'), default_yes=False): return self.library_name = n self.library_search = v QDialog.accept(self)
class ConfigDialog(QDialog): """Allow user to modify some persistent configuration settings.""" 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) def populate(self): """Fill the dialog.""" settings = QSettings(self) ppscannos = settings.value('ppscannos', type=str) if not ppscannos: #ppscannos = os.environ['HOME'] ppscannos = os.path.expanduser('~') ppscannos = ppscannos + '/ppscannos1/ppscannos1.py' self.lineEditPPScannos.setText(ppscannos) self.ppscannosChanged() defaultScanno = settings.value('defaultScannoFile', type=str) if defaultScanno: idx = self.comboScannoFiles.findText(defaultScanno) self.comboScannoFiles.setCurrentIndex(idx) #print('settings:', settings.allKeys()) #print('\tdefault:', settings.value('defaultScannoFile')) def ppscannosChanged(self): self.comboScannoFiles.clear() ppscannos = self.lineEditPPScannos.text() if not ppscannos: return scannoFiles = getRCFilesForDir(os.path.dirname(ppscannos)) if scannoFiles: for f in scannoFiles: (base, ext) = os.path.splitext(f) if ext == '.rc': self.comboScannoFiles.addItem(f) idx = self.comboScannoFiles.findText('regex.rc') if idx != -1: self.comboScannoFiles.setCurrentIndex(idx) def openFileDlg(self): """Open file picker for ppscannos.py file""" d = self.lineEditPPScannos.text() if d: d = os.path.dirname(d) dlg = QFileDialog(self, "Select PPScannos File...", None, "Python Files (*.py);;All Files (*)") dlg.setFileMode(QFileDialog.ExistingFile) if dlg.exec(): flist = dlg.selectedFiles() # returns a list if len(flist): self.lineEditPPScannos.setText(flist[0]) def ppscannosPath(self): return self.lineEditPPScannos.text() def scannoFileNames(self): lst = [] for i in range(self.comboScannoFiles.count()): lst.append(self.comboScannoFiles.itemText(i)) return lst
class ConditionEditor(QWidget): # {{{ ACTION_MAP = { 'bool' : ( (_('is true'), 'is true',), (_('is false'), 'is false'), (_('is undefined'), 'is undefined') ), 'ondevice' : ( (_('is true'), 'is set',), (_('is false'), 'is not set'), ), 'identifiers' : ( (_('has id'), 'has id'), (_('does not have id'), 'does not have id'), ), 'int' : ( (_('is equal to'), 'eq'), (_('is less than'), 'lt'), (_('is greater than'), 'gt') ), 'datetime' : ( (_('is equal to'), 'eq'), (_('is less than'), 'lt'), (_('is greater than'), 'gt'), (_('is set'), 'is set'), (_('is not set'), 'is not set'), (_('is more days ago than'), 'older count days'), (_('is fewer days ago than'), 'count_days'), (_('is more days from now than'), 'newer future days'), (_('is fewer days from now than'), 'older future days') ), 'multiple' : ( (_('has'), 'has'), (_('does not have'), 'does not have'), (_('has pattern'), 'has pattern'), (_('does not have pattern'), 'does not have pattern'), (_('is set'), 'is set'), (_('is not set'), 'is not set'), ), 'single' : ( (_('is'), 'is'), (_('is not'), 'is not'), (_('contains'), 'contains'), (_('does not contain'), 'does not contain'), (_('matches pattern'), 'matches pattern'), (_('does not match pattern'), 'does not match pattern'), (_('is set'), 'is set'), (_('is not set'), 'is not set'), ), } for x in ('float', 'rating'): ACTION_MAP[x] = ACTION_MAP['int'] def __init__(self, fm, parent=None): QWidget.__init__(self, parent) self.fm = fm self.action_map = self.ACTION_MAP self.l = l = QGridLayout(self) self.setLayout(l) texts = _('If the ___ column ___ values') try: one, two, three = texts.split('___') except: one, two, three = 'If the ', ' column ', ' value ' self.l1 = l1 = QLabel(one) l.addWidget(l1, 0, 0) self.column_box = QComboBox(self) l.addWidget(self.column_box, 0, 1) self.l2 = l2 = QLabel(two) l.addWidget(l2, 0, 2) self.action_box = QComboBox(self) l.addWidget(self.action_box, 0, 3) self.l3 = l3 = QLabel(three) l.addWidget(l3, 0, 4) self.value_box = QLineEdit(self) l.addWidget(self.value_box, 0, 5) self.column_box.addItem('', '') for key in sorted( conditionable_columns(fm), key=lambda key: sort_key(fm[key]['name'])): self.column_box.addItem(fm[key]['name'], key) self.column_box.setCurrentIndex(0) self.column_box.currentIndexChanged.connect(self.init_action_box) self.action_box.currentIndexChanged.connect(self.init_value_box) for b in (self.column_box, self.action_box): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(20) @dynamic_property def current_col(self): def fget(self): idx = self.column_box.currentIndex() return unicode_type(self.column_box.itemData(idx) or '') def fset(self, val): for idx in range(self.column_box.count()): c = unicode_type(self.column_box.itemData(idx) or '') if c == val: self.column_box.setCurrentIndex(idx) return raise ValueError('Column %r not found'%val) return property(fget=fget, fset=fset) @dynamic_property def current_action(self): def fget(self): idx = self.action_box.currentIndex() return unicode_type(self.action_box.itemData(idx) or '') def fset(self, val): for idx in range(self.action_box.count()): c = unicode_type(self.action_box.itemData(idx) or '') if c == val: self.action_box.setCurrentIndex(idx) return raise ValueError('Action %r not valid for current column'%val) return property(fget=fget, fset=fset) @property def current_val(self): ans = unicode_type(self.value_box.text()).strip() if self.current_col == 'languages': rmap = {lower(v):k for k, v in lang_map().iteritems()} ans = rmap.get(lower(ans), ans) return ans @dynamic_property def condition(self): def fget(self): c, a, v = (self.current_col, self.current_action, self.current_val) if not c or not a: return None return (c, a, v) def fset(self, condition): c, a, v = condition if not v: v = '' v = v.strip() self.current_col = c self.current_action = a self.value_box.setText(v) return property(fget=fget, fset=fset) def init_action_box(self): self.action_box.blockSignals(True) self.action_box.clear() self.action_box.addItem('', '') col = self.current_col if col: m = self.fm[col] dt = m['datatype'] if dt in self.action_map: actions = self.action_map[dt] else: if col == 'ondevice': k = 'ondevice' elif col == 'identifiers': k = 'identifiers' else: k = 'multiple' if m['is_multiple'] else 'single' actions = self.action_map[k] for text, key in actions: self.action_box.addItem(text, key) self.action_box.setCurrentIndex(0) self.action_box.blockSignals(False) self.init_value_box() def init_value_box(self): self.value_box.setEnabled(True) self.value_box.setText('') self.value_box.setInputMask('') self.value_box.setValidator(None) col = self.current_col if not col: return action = self.current_action if not action: return m = self.fm[col] dt = m['datatype'] tt = '' if col == 'identifiers': tt = _('Enter either an identifier type or an ' 'identifier type and value of the form identifier:value') elif col == 'languages': tt = _('Enter a 3 letter ISO language code, like fra for French' ' or deu for German or eng for English. You can also use' ' the full language name, in which case calibre will try to' ' automatically convert it to the language code.') elif dt in ('int', 'float', 'rating'): tt = _('Enter a number') v = QIntValidator if dt == 'int' else QDoubleValidator self.value_box.setValidator(v(self.value_box)) elif dt == 'datetime': if action == 'count_days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the maximum days old the item can be. Zero is today. ' 'Dates in the future always match') elif action == 'older count days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the minimum days old the item can be. Zero is today. ' 'Dates in the future never match') elif action == 'older future days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the maximum days in the future the item can be. ' 'Zero is today. Dates in the past always match') elif action == 'newer future days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the minimum days in the future the item can be. ' 'Zero is today. Dates in the past never match') else: self.value_box.setInputMask('9999-99-99') tt = _('Enter a date in the format YYYY-MM-DD') else: tt = _('Enter a string.') if 'pattern' in action: tt = _('Enter a regular expression') elif m.get('is_multiple', False): tt += '\n' + _('You can match multiple values by separating' ' them with %s')%m['is_multiple']['ui_to_list'] self.value_box.setToolTip(tt) if action in ('is set', 'is not set', 'is true', 'is false', 'is undefined'): self.value_box.setEnabled(False)
class PreferencesDialog(QDialog): #the user preferences itself def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Preferences') self.resize(600, 240) layout = QHBoxLayout() preview = Preview(self) #Antonio has a problem with the width of Preview form = QFormLayout() self.widthSB = QSpinBox() self.heightSB = QSpinBox() self.widthSB.setRange(1, 1000) self.heightSB.setRange(1, 1000) self.widthSB.setValue(label_size[0]) self.heightSB.setValue(label_size[1]) form.addRow('Width', self.widthSB) form.addRow('Height', self.heightSB) self.spacingDS = DoubleSpin() self.spacingDS.setX(spacing[0]) self.spacingDS.setY(spacing[1]) form.addRow('Spacing', self.spacingDS) self.offsetDS = DoubleSpin() self.offsetDS.setX(first_label_offset[0]) self.offsetDS.setY(first_label_offset[1]) form.addRow('Offset', self.offsetDS) self.p1 = DoubleSpin() self.p1.setX(item_positions['article'][0]) self.p1.setY(item_positions['article'][1]) form.addRow('p1', self.p1) self.p2 = DoubleSpin() self.p2.setX(item_positions['week'][0]) self.p2.setY(item_positions['week'][1]) form.addRow('p2', self.p2) self.p3 = DoubleSpin() self.p3.setX(item_positions['lot'][0]) self.p3.setY(item_positions['lot'][1]) form.addRow('p3', self.p3) self.p4 = DoubleSpin() self.p4.setX(item_positions['code'][0]) self.p4.setY(item_positions['code'][1]) form.addRow('p4', self.p4) self.qr_sizeDS = DoubleSpin() self.qr_sizeDS.setX(qr_size[0]) self.qr_sizeDS.setY(qr_size[1]) form.addRow('QR size', self.qr_sizeDS) self.alignament_mark = DoubleSpin() self.alignament_mark.setX( item_positions['logo'] [0]) #instead of logo, position of alignment_mark is used self.alignament_mark.setY(item_positions['logo'][1]) form.addRow('Alignment mark', self.alignament_mark) self.numberofColumnsSB = QSpinBox() self.numberofColumnsSB.setRange(1, 10) self.numberofColumnsSB.setValue(n_columns) form.addRow('Number of columns', self.numberofColumnsSB) self.numberofRowsSB = QSpinBox() self.numberofRowsSB.setRange(1, 50) self.numberofRowsSB.setValue(n_rows_per_page) form.addRow('Number of rows', self.numberofRowsSB) self.fontSizeSB = QSpinBox() self.fontSizeSB.setRange(4, 25) self.fontSizeSB.setValue(font['size']) form.addRow('Font size', self.fontSizeSB) self.frame_visible = QComboBox() self.frame_visible.addItem('True') self.frame_visible.addItem('False') form.addRow('Frame visible?', self.frame_visible) pbOk = QPushButton('OK') pbOk.clicked.connect(self.accept) form.addRow('', pbOk) pbCancel = QPushButton('Cancel') pbCancel.clicked.connect(self.reject) form.addRow('', pbCancel) layout.addWidget(preview) layout.addLayout(form) self.setLayout(layout)
class PieChart (QGraphicsView): def __init__(self,parent,total_value): super(PieChart,self).__init__(parent) self.my_scene = QGraphicsScene() #self.my_scene.setSceneRect(self.sceneRect()) self.setScene(self.my_scene) #self.setBackgroundBrush(QBrush(QtCore.Qt.black, QtCore.Qt.SolidPattern)); self.total_value = total_value self.initialize = False self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.margin = {'top':10,'bottom':10,'left':10,'right':10} self.space = 30 self.pie_items = [] def setTotal (self, total): self.total_value = total # def setData (self,list_item): # # rect = QGraphicsRectItem(self.sceneRect()) # rect.setBrush(QColor("red")) # self.scene().addItem(rect) def setData (self,list_items): size = min(self.frameSize().width()/2.0,self.frameSize().height()) self.size_pie = QSize(size,size) #print ('size pie ',self.size_pie) if self.initialize == False: self.c_box = QComboBox() self.c_box.addItem("all") self.c_box.addItem("alive") self.c_box.addItem("dead") self.c_box.currentIndexChanged.connect(self.update) proxy = self.my_scene.addWidget(self.c_box) x = self.size_pie.width()+ self.space proxy.setPos(QPointF(x,self.margin['top'])) self.initialize = True self.data = list_items self.update() def update(self): restant = 360 i = 0 #self.my_scene.clear() for item in self.pie_items : self.my_scene.removeItem(item) self.pie_items = [] self.scene().setSceneRect(QRectF(0,0,self.frameSize().width(),self.frameSize().height())) #print ('size',self.scene().sceneRect()) #proxy = QGraphicsProxyWidget () for item in self.data : if (i==len(self.data)-1 ): angle = restant else: try : angle = int(360*item[self.c_box.currentText()]/self.total_value[self.c_box.currentText()]) except ZeroDivisionError: angle = 0 ellipse = Section(0,0,self.size_pie.width(),self.size_pie.height()) y = (self.parent().size().height()-self.size_pie.height())/2.0 x_pie = ((self.parent().size().width()/2.0)-self.size_pie.height())/2.0 ellipse.setPos(x_pie,y) ellipse.setStartAngle(16*(360-restant)) ellipse.setSpanAngle(angle*16) ellipse.setBrush(item['color']) self.my_scene.addItem(ellipse) self.pie_items.append(ellipse) # text pourcentage a afficher dans les portions de disque try : v = (item[self.c_box.currentText()]/self.total_value[self.c_box.currentText()])*100 except ZeroDivisionError : v = 0 text = QGraphicsSimpleTextItem("{0:5.2f}".format(v)+"%") trans = QTransform().translate(x_pie+self.size_pie.width()/2.0,y+self.size_pie.height()/2.0).rotate(((360-restant)+angle/2.0)*-1) pts = trans.map(QPointF(self.size_pie.width()/3.0,0)) text.setPos(pts.x(),pts.y()) self.my_scene.addItem(text) self.pie_items.append(text) #libelle rect = QGraphicsRectItem(0,0,10,10) x = x_pie + self.size_pie.width()+ self.space interval_height = (self.parent().size().height()-self.margin['top']-self.margin['bottom'])/(len(self.data)+1) rect.setPos(QPointF(x,self.margin['top']+((i+1)*interval_height))) rect.setBrush(item['color']) self.my_scene.addItem(rect) self.pie_items.append(rect) text = QGraphicsSimpleTextItem(item['label']+ " ("+str(int(item[self.c_box.currentText()]))+")") pts = rect.pos() transform = QTransform().translate(30, 0) pts = transform.map(pts) text.setPos(pts) self.my_scene.addItem(text) self.pie_items.append(text) restant = restant - angle i +=1 # self.fitInView(self.scene.sceneRect())
class Window(QWidget): ext_list = ['mkv', 'mp4', 'avi'] def __init__(self): QWidget.__init__(self) self.v_box = QVBoxLayout() self.v_dir = QVBoxLayout() self.v_ext = QVBoxLayout() self.v_av = QVBoxLayout() self.H_default_save_dir = QHBoxLayout() self.H_default_ext = QHBoxLayout() self.H_av = QHBoxLayout() self.H_save = QHBoxLayout() self.settings = xml.ParseXMLSettings() self.txt_default_dir = QLineEdit(self) self.drpdwn_av = QComboBox(self) self.drpdwn_ext = QComboBox(self) self.shortcut = QShortcut(QKeySequence('Ctrl+W'), self) self.shortcut.activated.connect(self.close) self.initUI() self.v_box.addSpacing(12) self.H_av.addSpacing(12) self.H_default_ext.addSpacing(12) self.H_default_save_dir.addSpacing(12) self.H_save.addSpacing(12) self.setLayout(self.v_box) self.setGeometry(200, 200, 250, 150) self.setWindowTitle('Global Settings') def initUI(self): self.txt_default_dir.setText(self.settings.settings_list['save_dir']) self.txt_default_dir.setEnabled(False) lbl_default_dir = QLabel(self) lbl_default_dir.setText('Default Directory: ') btn_default_dir = QPushButton(self) btn_default_dir.setText('Change...') self.drpdwn_av.addItem(self.settings.settings_list['av']) lbl_av = QLabel(self) lbl_av.setText('Record Audio and Video? ') self.drpdwn_ext.addItem(self.settings.settings_list['ext']) lbl_ext = QLabel(self) lbl_ext.setText('Video Extension: ') btn_save = QPushButton(self) btn_save.setText('Save changes...') btn_default_dir.clicked.connect(lambda: self.change_dir()) btn_save.clicked.connect(self.save) if self.settings.settings_list['av'] == 'True': self.drpdwn_av.addItem('False') else: self.drpdwn_av.addItem('True') for ext in self.ext_list: if ext != self.settings.settings_list['ext']: self.drpdwn_ext.addItem(ext) self.v_dir.addWidget(lbl_default_dir) self.H_default_save_dir.addWidget(self.txt_default_dir) self.H_default_save_dir.addWidget(btn_default_dir) self.v_dir.addLayout(self.H_default_save_dir) self.v_av.addWidget(lbl_av) self.H_av.addWidget(self.drpdwn_av) self.v_av.addLayout(self.H_av) self.v_ext.addWidget(lbl_ext) self.H_default_ext.addWidget(self.drpdwn_ext) self.v_ext.addLayout(self.H_default_ext) self.H_save.addWidget(btn_save) self.v_ext.addStretch(1) self.v_av.addStretch(1) self.v_dir.addStretch(1) self.v_box.addLayout(self.v_dir) self.v_box.addLayout(self.v_av) self.v_box.addLayout(self.v_ext) self.v_box.addLayout(self.H_save) self.v_box.addStretch(1) def save(self): if self.drpdwn_ext.currentText( ) != self.settings.settings_list['ext'] or self.drpdwn_av.currentText( ) != self.settings.settings_list['av']: dlg = dialog.QuestionDialog('Are you ready to save changes?') if dlg.clickedButton() == dlg.yes: if self.drpdwn_ext.currentText( ) != self.settings.settings_list['ext']: self.settings.edit('ext', self.drpdwn_ext.currentText()) SETTINGS.settings_list[ 'ext'] = self.drpdwn_ext.currentText() if self.drpdwn_av.currentText( ) != self.settings.settings_list['av']: self.settings.edit('av', self.drpdwn_av.currentText()) SETTINGS.settings_list['av'] = self.drpdwn_av.currentText() else: pass def change_dir(self): dlg = str(QFileDialog.getExistingDirectory(self, "Select Directory")) if dlg != "": self.settings.edit('save_dir', dlg) self.txt_default_dir.setText(dlg) SETTINGS.settings_list['save_dir'] = dlg
class ConditionEditor(QWidget): # {{{ ACTION_MAP = { 'bool' : ( (_('is true'), 'is true',), (_('is false'), 'is false'), (_('is undefined'), 'is undefined') ), 'ondevice' : ( (_('is true'), 'is set',), (_('is false'), 'is not set'), ), 'identifiers' : ( (_('has id'), 'has id'), (_('does not have id'), 'does not have id'), ), 'int' : ( (_('is equal to'), 'eq'), (_('is less than'), 'lt'), (_('is greater than'), 'gt') ), 'datetime' : ( (_('is equal to'), 'eq'), (_('is less than'), 'lt'), (_('is greater than'), 'gt'), (_('is set'), 'is set'), (_('is not set'), 'is not set'), (_('is more days ago than'), 'older count days'), (_('is fewer days ago than'), 'count_days'), (_('is more days from now than'), 'newer future days'), (_('is fewer days from now than'), 'older future days') ), 'multiple' : ( (_('has'), 'has'), (_('does not have'), 'does not have'), (_('has pattern'), 'has pattern'), (_('does not have pattern'), 'does not have pattern'), (_('is set'), 'is set'), (_('is not set'), 'is not set'), ), 'single' : ( (_('is'), 'is'), (_('is not'), 'is not'), (_('matches pattern'), 'matches pattern'), (_('does not match pattern'), 'does not match pattern'), (_('is set'), 'is set'), (_('is not set'), 'is not set'), ), } for x in ('float', 'rating'): ACTION_MAP[x] = ACTION_MAP['int'] def __init__(self, fm, parent=None): QWidget.__init__(self, parent) self.fm = fm self.action_map = self.ACTION_MAP self.l = l = QGridLayout(self) self.setLayout(l) texts = _('If the ___ column ___ values') try: one, two, three = texts.split('___') except: one, two, three = 'If the ', ' column ', ' value ' self.l1 = l1 = QLabel(one) l.addWidget(l1, 0, 0) self.column_box = QComboBox(self) l.addWidget(self.column_box, 0, 1) self.l2 = l2 = QLabel(two) l.addWidget(l2, 0, 2) self.action_box = QComboBox(self) l.addWidget(self.action_box, 0, 3) self.l3 = l3 = QLabel(three) l.addWidget(l3, 0, 4) self.value_box = QLineEdit(self) l.addWidget(self.value_box, 0, 5) self.column_box.addItem('', '') for key in sorted( conditionable_columns(fm), key=lambda(key): sort_key(fm[key]['name'])): self.column_box.addItem(fm[key]['name'], key) self.column_box.setCurrentIndex(0) self.column_box.currentIndexChanged.connect(self.init_action_box) self.action_box.currentIndexChanged.connect(self.init_value_box) for b in (self.column_box, self.action_box): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(20) @dynamic_property def current_col(self): def fget(self): idx = self.column_box.currentIndex() return unicode(self.column_box.itemData(idx) or '') def fset(self, val): for idx in range(self.column_box.count()): c = unicode(self.column_box.itemData(idx) or '') if c == val: self.column_box.setCurrentIndex(idx) return raise ValueError('Column %r not found'%val) return property(fget=fget, fset=fset) @dynamic_property def current_action(self): def fget(self): idx = self.action_box.currentIndex() return unicode(self.action_box.itemData(idx) or '') def fset(self, val): for idx in range(self.action_box.count()): c = unicode(self.action_box.itemData(idx) or '') if c == val: self.action_box.setCurrentIndex(idx) return raise ValueError('Action %r not valid for current column'%val) return property(fget=fget, fset=fset) @property def current_val(self): ans = unicode(self.value_box.text()).strip() if self.current_col == 'languages': rmap = {lower(v):k for k, v in lang_map().iteritems()} ans = rmap.get(lower(ans), ans) return ans @dynamic_property def condition(self): def fget(self): c, a, v = (self.current_col, self.current_action, self.current_val) if not c or not a: return None return (c, a, v) def fset(self, condition): c, a, v = condition if not v: v = '' v = v.strip() self.current_col = c self.current_action = a self.value_box.setText(v) return property(fget=fget, fset=fset) def init_action_box(self): self.action_box.blockSignals(True) self.action_box.clear() self.action_box.addItem('', '') col = self.current_col if col: m = self.fm[col] dt = m['datatype'] if dt in self.action_map: actions = self.action_map[dt] else: if col == 'ondevice': k = 'ondevice' elif col == 'identifiers': k = 'identifiers' else: k = 'multiple' if m['is_multiple'] else 'single' actions = self.action_map[k] for text, key in actions: self.action_box.addItem(text, key) self.action_box.setCurrentIndex(0) self.action_box.blockSignals(False) self.init_value_box() def init_value_box(self): self.value_box.setEnabled(True) self.value_box.setText('') self.value_box.setInputMask('') self.value_box.setValidator(None) col = self.current_col if not col: return action = self.current_action if not action: return m = self.fm[col] dt = m['datatype'] tt = '' if col == 'identifiers': tt = _('Enter either an identifier type or an ' 'identifier type and value of the form identifier:value') elif col == 'languages': tt = _('Enter a 3 letter ISO language code, like fra for French' ' or deu for German or eng for English. You can also use' ' the full language name, in which case calibre will try to' ' automatically convert it to the language code.') elif dt in ('int', 'float', 'rating'): tt = _('Enter a number') v = QIntValidator if dt == 'int' else QDoubleValidator self.value_box.setValidator(v(self.value_box)) elif dt == 'datetime': if action == 'count_days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the maximum days old the item can be. Zero is today. ' 'Dates in the future always match') elif action == 'older count days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the minimum days old the item can be. Zero is today. ' 'Dates in the future never match') elif action == 'older future days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the maximum days in the future the item can be. ' 'Zero is today. Dates in the past always match') elif action == 'newer future days': self.value_box.setValidator(QIntValidator(self.value_box)) tt = _('Enter the minimum days in the future the item can be. ' 'Zero is today. Dates in the past never match') else: self.value_box.setInputMask('9999-99-99') tt = _('Enter a date in the format YYYY-MM-DD') else: tt = _('Enter a string.') if 'pattern' in action: tt = _('Enter a regular expression') elif m.get('is_multiple', False): tt += '\n' + _('You can match multiple values by separating' ' them with %s')%m['is_multiple']['ui_to_list'] self.value_box.setToolTip(tt) if action in ('is set', 'is not set', 'is true', 'is false', 'is undefined'): self.value_box.setEnabled(False)
class MethSimplex(QMainWindow): def __init__(self, ui): super(MethSimplex, self).__init__() self.ui = ui #self.ui.setupUi(self) #self.ventana = Simplex(self.ui) #Simplex self.numVariables = 0 self.numRestricciones = 0 self.columSR = 0 self.columSRcompletas = 0 self.numHolgura = 0 self.numArtificial = 0 self.numIteraciones = 0 self.solucion_optima = "" self.metodo = "" self.tituloMetodo = "" self.allTable = [] #Per y Simplex self.asignarComponentes() #Simplex self.editarComponentes() self.eventosDeBotones() self.eventocomboMetodo() def asignarComponentes(self): # Componentes de la interfaz Simplex # Paneles self.panelTablaU = QtWidgets.QFrame self.panelTablaU = self.ui.panelTblU self.panelFunYRest = QtWidgets.QFrame self.panelFunYRest = self.ui.panelVarRest # Combo box lista desplegables self.comboObjetivo = QtWidgets.QComboBox self.comboObjetivo = self.ui.cmbObjetivo self.comboMetodo = QtWidgets.QComboBox self.comboMetodo = self.ui.cmbMetodo # Etiquetas Labels self.etiquetaIteracion = QtWidgets.QLabel self.etiquetaIteracion = self.ui.lblIteracion self.etiquetaFunObj = QtWidgets.QLabel self.etiquetaFunObj = self.ui.lblFunObj self.etiquetaFuncionObjetivo = QtWidgets.QLabel self.etiquetaFuncionObjetivo = self.ui.lblFuncionObjetivo # Botones self.botonIteracion = QtWidgets.QPushButton self.botonIteracion = self.ui.btnIteracion self.botonPdf = QtWidgets.QPushButton self.botonPdf = self.ui.btnPdf self.botonCalcular = QtWidgets.QPushButton self.botonCalcular = self.ui.btnCalcular self.botonGenerar = QtWidgets.QPushButton self.botonGenerar = self.ui.btnGenerar # Campos de texto self.textFieldVar = QtWidgets.QLineEdit self.textFieldVar = self.ui.txtVar self.textFieldRestr = QtWidgets.QLineEdit self.textFieldRestr = self.ui.txtRestr # Tablas self.tablaVariables = QtWidgets.QTableWidget self.tablaVariables = self.ui.tblVariables self.tablaRestricciones = QtWidgets.QTableWidget self.tablaRestricciones = self.ui.tblRestricciones self.tablaU = QtWidgets.QTableWidget self.tablaU = self.ui.tbl_U self.tablaOperaciones = QtWidgets.QTableWidget self.tablaOperaciones = self.ui.tblOperaciones def editarComponentes(self): cmb = QtWidgets.QComboBox panel = QtWidgets.QFrame txt = QtWidgets.QLineEdit self.panelTablaU.setVisible(False) # Ocultar panel self.panelFunYRest.setVisible(False) objMetodo = ["Método Simplex", "Método Big M"] self.comboMetodo.clear() self.comboMetodo.addItems(objMetodo) # LLenar cmb Metodos objObjetivo = ["Minimizar", "Maximizar"] self.comboObjetivo.clear() self.comboObjetivo.addItems(objObjetivo) self.comboObjetivo.setVisible(False) self.botonPdf.setVisible(False) self.etiquetaFunObj.setVisible(False) def eventosDeBotones(self): self.botonGenerar.clicked.connect(self.cargarProceso) self.botonCalcular.clicked.connect(self.cargarProceso) self.botonIteracion.clicked.connect(self.cargarProceso) self.botonPdf.clicked.connect(self.cargarProceso) def show_popup_Informacion(self, titulo, mensaje): msg = QMessageBox() msg.setWindowTitle(titulo) msg.setIcon(QMessageBox.Information) msg.setText(mensaje) x = msg.exec_() def cargarProceso(self): boton = self.sender() if boton == self.botonGenerar: if not self.textFieldVar.text() or not self.textFieldRestr.text(): self.show_popup_Informacion( "Datos invalidos", "No se ingresaron correctamente los datos") else: self.mostrarLabels(False) self.panelFunYRest.setVisible(True) self.numVariables = int(self.textFieldVar.text()) self.numRestricciones = int(self.textFieldRestr.text()) self.llenarTablaVar() self.llenarTablaRestr() if self.comboMetodo.currentIndex() == 1: self.comboObjetivo.setVisible(True) elif boton == self.botonCalcular: self.allTable = [] self.matrizInicial() self.botonPdf.setVisible(False) self.metodo = "" self.tituloMetodo = "" if self.comboMetodo.currentIndex() == 0: self.metodo = "MetodoSimplex" self.tituloMetodo = "REPORTE MÉTODO SIMPLEX" else: self.metodo = "MetodoBigM" self.tituloMetodo = "REPORTE MÉTODO BIG M" elif boton == self.botonIteracion: if self.comboMetodo.currentIndex() == 0 or ( self.comboMetodo.currentIndex() == 1 and self.comboObjetivo.currentIndex() == 1): if self.seguirIteracionesSimplex() == True: self.iteraciones() else: self.botonPdf.setVisible(True) self.show_popup_Informacion( "Mensaje", "Se han terminado las iteraciones") else: if self.seguirIteracionesBigM() == True: self.iteraciones() else: self.botonPdf.setVisible(True) self.show_popup_Informacion( "Mensaje", "Se han terminado las iteraciones") else: self.solucion_optima = self.tablaU.item( (self.numRestricciones + 2), self.columSRcompletas + 1).text() self.generarReporte() #hilo = threading.Thread(target = self.generarReporte) #hilo.start() def mostrarLabels(self, estado): self.etiquetaFunObj.setVisible(estado) self.etiquetaFuncionObjetivo.setVisible(estado) self.tablaOperaciones.clear() self.tablaU.clear() self.panelTablaU.setVisible(estado) def llenarTablaVar(self): self.tablaVariables.clear() self.tablaVariables.setRowCount(1) self.tablaVariables.setColumnCount(self.numVariables) for i in range(self.numVariables): item1 = QTableWidgetItem(f"X{i+1}") item1.setBackground(QtGui.QColor(0, 153, 153)) self.tablaVariables.setHorizontalHeaderItem(i, item1) def llenarTablaRestr(self): self.tablaRestricciones.clear() self.tablaRestricciones.setRowCount(self.numRestricciones) self.tablaRestricciones.setColumnCount(self.numVariables) for j in range(self.numVariables): item1 = QTableWidgetItem(f"X{j+1}") item1.setBackground(QtGui.QColor(0, 153, 153)) self.tablaRestricciones.setHorizontalHeaderItem(j, item1) for i in range(self.numVariables, self.numVariables + 2): item = QTableWidgetItem(" ") self.tablaRestricciones.insertColumn(i) item.setBackground(QtGui.QColor(0, 153, 153)) self.tablaRestricciones.setHorizontalHeaderItem(i, item) fila = 0 colum = self.numVariables cmbMeth = self.comboMetodo for j in range(self.numRestricciones): self.cmbSigno = QComboBox() self.cmbSigno.addItem("<=") if cmbMeth.currentIndex() == 1: self.cmbSigno.addItem(">=") self.cmbSigno.addItem("=") self.tablaRestricciones.setCellWidget(fila, colum, self.cmbSigno) fila += 1 def eventocomboMetodo(self): self.comboMetodo.currentIndexChanged.connect(self.cambiocomboMetodo) def cambiocomboMetodo(self): fila = 0 colum = self.numVariables for j in range(self.numRestricciones): self.cmbSigno = QComboBox() self.cmbSigno.addItem("<=") if self.comboMetodo.currentIndex() == 0: # Metodo Simplex self.comboObjetivo.setCurrentIndex(1) # Maximizar self.comboObjetivo.setVisible(False) else: self.comboObjetivo.setCurrentIndex(0) # Minimizar self.comboObjetivo.setVisible(True) self.cmbSigno.addItem(">=") self.cmbSigno.addItem("=") self.tablaRestricciones.setCellWidget(fila, colum, self.cmbSigno) fila += 1 def guardarRestricciones(self): restriccionesString = [" "] * (self.numRestricciones + 1) columnas = self.numVariables + 2 valor = "" # restricciones comboOne = QtWidgets.QComboBox for i in range(0, len(restriccionesString) - 1, 1): for j in range(0, columnas, 1): if j < self.numVariables: valor = self.tablaRestricciones.item(i, j).text() if j == 0: restriccionesString[i] = valor + "X" + str(j + 1) else: if valor[0] == '-': restriccionesString[i] += valor + "X" + str(j + 1) else: restriccionesString[i] += "+" + \ valor + "X" + str(j + 1) elif j == self.numVariables: comboOne = self.tablaRestricciones.cellWidget( i, self.numVariables) datoSigno = comboOne.currentText() restriccionesString[i] += datoSigno else: valor = self.tablaRestricciones.item(i, j).text() restriccionesString[i] += valor # no negatividad restriccionesString[len(restriccionesString) - 1] = "" combo = QtWidgets.QComboBox signo = "" for fila in range(0, self.numRestricciones, 1): combo = self.tablaRestricciones.cellWidget(fila, columnas - 2) signo = combo.currentText() if signo == "=": signo = " sin signo de restricción " else: signo += "0; " restriccionesString[len(restriccionesString) - 1] += "X" + str(fila + 1) + signo return restriccionesString def matrizInicial(self): # Guarda las inecuaciones en el arreglo matriz inicial inecuaciones = self.sistemaRestricciones() # Definimos tamaño columnas y filas numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 matriz = [["0"] * numColumnas for i in range(numFilas)] # espacios en blanco y datos que no cambian matriz[0][0] = " " matriz[0][1] = "CJ" matriz[0][numColumnas - 1] = " " matriz[1][0] = "CB" matriz[1][1] = "XB" matriz[1][numColumnas - 1] = "BI" matriz[numFilas - 2][0] = " " matriz[numFilas - 2][1] = "ZJ" matriz[numFilas - 1][0] = " " matriz[numFilas - 1][1] = "ZJ-CJ" matriz[numFilas - 1][numColumnas - 1] = " " # Xb, Cj filas numVar = 0 numArt = 0 funcion = "" stringDecimal = "" for j in range(2, (numColumnas - 1), 1): # Cj Xb if numVar < self.numVariables: stringDecimal = self.tablaVariables.item(0, numVar).text() matriz[0][j] = self.devolverValorSR(stringDecimal) if matriz[0][j] == "Dato vacio": print("Pendiente Thow Null") funcion += " " + str(matriz[0][j]) matriz[1][j] = "X" + str(numVar + 1) funcion += str(matriz[1][j]) + " +" numVar += 1 elif numVar < self.columSR: matriz[0][j] = "0" matriz[1][j] = "X" + str(numVar + 1) numVar += 1 else: if self.comboMetodo.currentIndex() == 0: # Metodo Simplex matriz[0][j] = "1" else: # Metodo Big M if self.comboObjetivo.currentIndex() == 0: # Minimizar matriz[0][j] = "M" else: matriz[0][j] = "-M" matriz[1][j] = "A" + str(numArt + 1) numArt += 1 # Ya no se lanza excepcion se pueden mostrar la tablaU y las etiquetas self.mostrarLabels(True) minmax = "" # Mostrar minimizar o maximizar if self.comboMetodo.currentIndex( ) == 0 or self.comboObjetivo.currentIndex() == 1: minmax = "Max Z = " else: minmax = "Min Z = " self.etiquetaFuncionObjetivo.setText(" " + minmax + funcion[0:len(funcion) - 1]) # Guardamos inecuaciones en matriz inicial for q in range(0, self.numRestricciones, 1): # filas for w in range(0, self.columSRcompletas, 1): # columnas matriz[q + 2][w + 2] = str(inecuaciones[q][w]) # Agregar Cb y Xb columnas if str(inecuaciones[q][w]) == "1" and w >= self.numVariables: matriz[q + 2][0] = matriz[0][w + 2] # Cb matriz[q + 2][1] = matriz[1][w + 2] # Xb # Obtener fila zj stringZj = "" acumulaZj = "" for col in range(0, self.columSRcompletas, 1): acumulaZj = "" for fila in range(0, self.numRestricciones, 1): stringZj = self.guardarZj(str(matriz[fila + 2][0]), str(matriz[fila + 2][col + 2])) acumulaZj += stringZj + ";" matriz[numFilas - 2][col + 2] = self.devolverZj(acumulaZj) # obtener fila cj-zj for col in range(2, (numColumnas - 1), 1): matriz[numFilas - 1][col] = self.devolverZjCj( str(matriz[0][col]), str(matriz[numFilas - 2][col])) # mostrar matriz en la tabla self.tablaU.clear() self.tablaU.setRowCount(numFilas) self.tablaU.setColumnCount(numColumnas) for j in range(numColumnas): item1 = QTableWidgetItem(" ") #item1.setBackground(QtGui.QColor(0, 153, 153)) self.tablaU.setHorizontalHeaderItem(j, item1) for row in range(0, numFilas, 1): for col in range(0, numColumnas, 1): item = QTableWidgetItem(str(matriz[row][col])) self.tablaU.setItem(row, col, item) self.tablaU.resizeColumnsToContents() # pintar pivote self.pintarPivote() self.numIteraciones = 0 self.etiquetaIteracion.setText(" " + str(self.numIteraciones)) # Guardar tabla para el pdf fila = self.numRestricciones + 4 columna = self.columSRcompletas + 2 tablaInicial = [] for f in range(fila): filaAnterior = [] for c in range(columna): item = self.tablaU.item(f, c).text() filaAnterior.append(item) tablaInicial.append(filaAnterior) self.allTable.append(tablaInicial) def guardarZj(self, cb, numero): multiCb = "" fracNum = Fraccion.Fraccion(0, 0) fracCB = Fraccion.Fraccion(0, 0) if numero == "0" or cb == "0": multiCb = "0" elif cb == "M": multiCb = numero + "M" elif cb == "-M": fracNum = fracNum.deTablaFraccion(numero) fracCB.setNumerador(-1) fracCB.setDenominador(1) multiCb = fracCB.multiplicar(fracNum).__str__() + "M" else: fracNum = fracNum.deTablaFraccion(numero) fracCB = fracCB.deTablaFraccion(cb) multiCb = fracCB.multiplicar(fracNum).__str__() return multiCb def devolverZj(self, acumulaZj): acumulaZj = acumulaZj[0:len(acumulaZj) - 1] # quitar ultimo ; arregloZj = acumulaZj.split(";") zjfinal = "" llevaM = False llevaFrac = False claseM = ClaseM.ClaseM(Fraccion.Fraccion(0, 0), "M") claseMAcum = ClaseM.ClaseM(Fraccion.Fraccion(0, 0), "M") claseMAcum.setCoeficiente(Fraccion.Fraccion(0, 1)) fracAcumuladora = Fraccion.Fraccion(0, 1) frac = Fraccion.Fraccion(0, 0) i = 0 for k in range(0, len(arregloZj), 1): if claseM.esM(arregloZj[k]): claseM = claseM.obtenerM(arregloZj[k]) claseMAcum = claseMAcum.sumaM(claseM) llevaM = True elif not arregloZj[k] == "0": fracAcumuladora = fracAcumuladora.sumar( frac.deTablaFraccion(arregloZj[k])) llevaFrac = True if llevaM == False: zjfinal = fracAcumuladora.__str__() elif (llevaFrac == True) and (fracAcumuladora.__str__()[0] == "-"): zjfinal = claseMAcum.__str__() + fracAcumuladora.__str__() elif (llevaFrac == True) and (not fracAcumuladora.__str__()[0] == "-"): newM = "" if not claseMAcum.__str__() == "0": newM = claseMAcum.__str__() + "+" zjfinal = newM + fracAcumuladora.__str__() else: zjfinal = claseMAcum.__str__() corte0 = "" if len(zjfinal) > 2: corte0 = zjfinal[len(zjfinal) - 2:len(zjfinal)] if (corte0 == "+0") or (corte0 == "-0"): zjfinal = zjfinal[0:len(zjfinal) - 2] return zjfinal def devolverZjCj(self, cj, zj): zjcj = "" newCj = "" corteM = "" corteFrac = "" posM = 0 fraccionZj = Fraccion.Fraccion(0, 0) fraccionCj = Fraccion.Fraccion(0, 0) fracCorte = Fraccion.Fraccion(0, 0) zjM = ClaseM.ClaseM(Fraccion.Fraccion(0, 0), "M") cjM = ClaseM.ClaseM(Fraccion.Fraccion(0, 0), "M") if cj == "0" and zj == "0": # 0 y 0 zjcj = "0" elif zj == "" or zj == " ": zjcj = cj elif zjM.esM(zj) == True and cjM.esM(cj) == True: # ambas son M if cj == "M": cj = "1M" if cj == "-M": cj = "-1M" if zj[len(zj) - 1] == "0": #0-0 zj = zj[0:len(zj) - 2] posM = zj.find('M') # separar fraccion de M if posM == len(zj) - 1: # no tiene nada despues de M corteFrac = "" else: # si tiene despues de M corteFrac = zj[posM + 1:len(zj)] if corteFrac[0] == '-': corteFrac = "+" + corteFrac[1:len(corteFrac)] else: corteFrac = "-" + corteFrac[1:len(corteFrac)] corteM = zj[0:posM + 1] # cambiar signo al corte M if corteM[0] == '-': corteM = corteM[1:len(corteM)] else: corteM = "-" + corteM cjM = cjM.obtenerM(cj) zjM = zjM.obtenerM(corteM) cjM = cjM.sumaM(zjM) zjcj = cjM.__str__() + corteFrac elif zjM.esM(zj): # cj es numero zj = tiene M posM = zj.find('M') # separar M de fraccion if posM == len(zj) - 1: # no tiene nada despues de M fracCorte.setNumerador(0) fracCorte.setDenominador(1) else: # si tiene despues de M corteFrac = zj[posM + 1:len(zj)] # cambiar signo a fraccion if corteFrac[0] == '-': corteFrac = corteFrac[1:len(corteFrac)] else: corteFrac = "-" + corteFrac[1:len(corteFrac)] fracCorte = fracCorte.deTablaFraccion(corteFrac) corteM = zj[0:posM + 1] # cambiar signo al corte M if corteM[0] == '-': corteM = corteM[1:len(corteM)] else: corteM = "-" + corteM # hacer calculo para la fraccion if cj == "0": fraccionCj.setNumerador(0) fraccionCj.setDenominador(1) fraccionCj = fraccionCj.deTablaFraccion(cj) else: fraccionCj = fraccionCj.deTablaFraccion(cj) fraccionCj = fraccionCj.sumar(fracCorte) if not fraccionCj.__str__()[0] == '-': newCj = "+" + fraccionCj.__str__() else: newCj = fraccionCj.__str__() if newCj[len(newCj) - 1] == '0': newCj = "" zjcj = corteM + newCj elif cjM.esM(cj): # cj tiene M zj es fraccion if cj == 'M': corteM = "1M" if cj == "-M": corteM = "-1M" if zj == "0": zjcj = corteM else: if zj[0] == '-': zj = "+" + zj[1:len(zj)] else: zj = "-" + zj zjcj = corteM + zj else: fraccionCj = fraccionCj.deTablaFraccion(cj) if zj[0] == '-': zj = zj[1:len(zj)] else: zj = "-" + zj fraccionZj = fraccionZj.deTablaFraccion(zj) zjcj = fraccionCj.sumar(fraccionZj).__str__() return zjcj def sistemaRestricciones(self): sinExpcecion = False self.columSR = 0 self.columSRcompletas = 0 self.numHolgura = 0 self.numArtificial = 0 # numero de columnas que ocupan las variables de la funcion objtivo self.columSR = self.numVariables # ciclo que aumenta columnas combo = QtWidgets.QComboBox for i in range(0, self.numRestricciones, 1): combo = self.tablaRestricciones.cellWidget(i, self.numVariables) signo = combo.currentText() if signo == ">=": self.numHolgura += 1 self.numArtificial += 1 elif signo == "=": self.numArtificial += 1 else: self.numHolgura += 1 self.columSR += self.numHolgura self.columSRcompletas = self.columSR + self.numArtificial + 1 # Matriz restricciones = [[0] * self.columSRcompletas for i in range(self.numRestricciones)] # Ciclo para agregar los coeficientes de la funcion objetivo stringDecimal1 = "" for iResFila in range(0, self.numRestricciones, 1): if sinExpcecion: break for iResCol in range(0, self.numVariables, 1): stringDecimal1 = self.tablaRestricciones.item( iResFila, iResCol).text() restricciones[iResFila][iResCol] = self.devolverValorSR( stringDecimal1) if restricciones[iResFila][iResCol] == "Dato vacio": sinExpcecion = True break if sinExpcecion == False: numIguales = 0 combo = QtWidgets.QComboBox for iResFila in range(0, self.numRestricciones, 1): combo = self.tablaRestricciones.cellWidget( iResFila, self.numVariables) signo = combo.currentText() for iResCol in range(0, self.numHolgura, 1): if iResFila == (iResCol + numIguales): if signo == ">=": restricciones[iResFila][iResCol + self.numVariables] = "-1" elif signo == "=": restricciones[iResFila][iResCol + self.numVariables] = "0" else: restricciones[iResFila][iResCol + self.numVariables] = "1" else: restricciones[iResFila][iResCol + self.numVariables] = "0" if signo == "=": numIguales += 1 saltoFila = 0 combo = QtWidgets.QComboBox for iResFila in range(0, self.numRestricciones, 1): combo = self.tablaRestricciones.cellWidget( iResFila, self.numVariables) signo = combo.currentText() for iResCol in range(0, self.numArtificial, 1): if iResFila == (iResCol + saltoFila): if signo == "<=": restricciones[iResFila][iResCol + self.columSR] = "0" else: restricciones[iResFila][iResCol + self.columSR] = "1" else: restricciones[iResFila][iResCol + self.columSR] = "0" if signo == "<=": saltoFila += 1 stringDecimal2 = "" for bi in range(0, self.numRestricciones, 1): stringDecimal2 = self.tablaRestricciones.item( bi, self.tablaRestricciones.columnCount() - 1).text() restricciones[bi][self.columSRcompletas - 1] = self.devolverValorSR(stringDecimal2) if restricciones[bi][self.columSRcompletas - 1] == "Dato vacio": sinExpcecion = True break if sinExpcecion: return # retorna None else: return restricciones else: return # retorna None def devolverValorSR(self, stringDecimal): try: frac = Fraccion.Fraccion(0, 0) decimal = float(0) if stringDecimal == "0" or stringDecimal == "-0" or stringDecimal == "0.0": decimal = 1 elif frac.posicionBarra(stringDecimal) == -1: decimal = float(stringDecimal) else: decimal = 1 if decimal % int(decimal) == 0: return stringDecimal else: return frac.toFraccion(decimal).__str__() except ValueError: return "Dato vacio" def variableSalida(self): fraccionAij = Fraccion.Fraccion(0, 0) fraccionBi = Fraccion.Fraccion(0, 0) vSal = float(0) siguiente = float(0) numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 menor = 2 # posicion ubicacion ve = self.variableEntrada() # ubicacion de la variable de entrada entra = True # booleana para ejecutarse una sola vez aij = float(0) bi = float(0) stringAij = "" stringBi = "" for i in range(2, (numFilas - 2), 1): # ciclo recorre las filas de las inecuaciones stringAij = self.tablaU.item(i, ve).text() if fraccionAij.posicionBarra(stringAij) == -1: aij = float(stringAij) else: fraccionAij = fraccionAij.deTablaFraccion(stringAij) aij = fraccionAij.toDecimal() stringBi = self.tablaU.item(i, numColumnas - 1).text() if fraccionBi.posicionBarra(stringBi) == -1: bi = float(stringBi) else: fraccionBi = fraccionBi.deTablaFraccion(stringBi) bi = fraccionBi.toDecimal() if (aij > 0) and (bi > 0): # para que no haya division entre 0 siguiente = float(bi / aij) if entra: # solo se ejecuta una vez al inicio del ciclo vSal = siguiente # vSal toma el primer valor de siguiente entra = False menor = i if siguiente < vSal: # condicional para que determinar el menor valor vSal = siguiente menor = i return menor def variableEntrada(self): numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 contador = 3 posicion = 2 # primera posicion fraccionVent = Fraccion.Fraccion(0, 0) fraccionSig = Fraccion.Fraccion(0, 0) vEnt = float(0) siguiente = float(0) stringVent = "" stringSig = "" claseM = ClaseM.ClaseM(Fraccion.Fraccion(0, 0), "M") stringVent = claseM.obtenerValorSinM( self.tablaU.item(numFilas - 1, 2).text()) if fraccionVent.posicionBarra(stringVent) == -1: vEnt = float(stringVent) else: fraccionVent = fraccionVent.deTablaFraccion(stringVent) vEnt = fraccionVent.toDecimal() while contador < numColumnas - 1: # ciclo para hallar stringSig = claseM.obtenerValorSinM( self.tablaU.item(numFilas - 1, contador).text()) if fraccionSig.posicionBarra(stringSig) == -1: siguiente = float(stringSig) else: fraccionSig = fraccionSig.deTablaFraccion(stringSig) siguiente = fraccionSig.toDecimal() if self.comboMetodo.currentIndex( ) == 0 or self.comboObjetivo.currentIndex() == 1: if siguiente > vEnt: # si el siguiente valor es menor vEnt = siguiente # vEnt toma ese valor para ser comparado en la siguiente vuelta del ciclo posicion = contador # guarda la ubicacion de la columna else: if siguiente < vEnt: # si el siguiente valor es menor vEnt = siguiente # vEnt toma ese valor para ser comparado en la siguiente vuelta del ciclo posicion = contador contador += 1 return posicion def iteraciones(self): numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 # matriz para tomar los datos actuales de la tabla anteriorIteracion = [[" "] * numColumnas for i in range(numFilas)] # matriz para insertar nuevos datos a la tabla nuevaIteracion = [[" "] * numColumnas for i in range(numFilas)] # llenar matriz anterior for i in range(0, numFilas, 1): for j in range(0, numColumnas, 1): anteriorIteracion[i][j] = self.tablaU.item(i, j).text() # llenar 2 primeras filas de la nueva matriz for k in range(0, 2, 1): for m in range(0, numColumnas, 1): nuevaIteracion[k][m] = self.tablaU.item(k, m).text() col = self.variableEntrada() # ubicacion de la columna del pivote fila = self.variableSalida() # ubicacion de la fila del pivote # obtener fila 1 f1Fila1 = Fraccion.Fraccion(0, 0) f2Fila1 = Fraccion.Fraccion(0, 0) fila1 = [Fraccion.Fraccion(0, 0)] * (numColumnas - 2) string1Fila1 = "" string2Fila1 = "" for i in range(0, len(fila1), 1): string1Fila1 = str(anteriorIteracion[fila][2 + i]) string2Fila1 = str(anteriorIteracion[fila][col]) f1Fila1 = f1Fila1.deTablaFraccion(string1Fila1) fila1[i] = f1Fila1.dividir(f2Fila1.deTablaFraccion(string2Fila1)) # obtener las otras filas 0 y llenar la tabla de ecuaciones numColEcuaciones = numColumnas - 1 numFilaEcuaciones = (self.numRestricciones - 1) * 6 matrizEcuaciones = [[" "] * numColEcuaciones for i in range(numFilaEcuaciones)] # matriz stringNega = "" stringFila0 = "" fracNega = Fraccion.Fraccion(0, 0) fracFila0 = Fraccion.Fraccion(0, 0) fracMulti0 = Fraccion.Fraccion(0, 0) saltoFila = -6 multiplicador = "" for iterador in range(2, (numFilas - 2), 1): if not iterador == fila: # si se cumpla se calcula el valor de las nuevas filas 0 saltoFila += 6 for j in range(2, numColumnas, 1): stringNega = str(anteriorIteracion[iterador][col]) fracNega = fracNega.deTablaFraccion(stringNega) fracNega = fracNega.multiplicar(Fraccion.Fraccion(-1, 1)) stringFila0 = str(anteriorIteracion[iterador][j]) fracFila0 = fracFila0.deTablaFraccion(stringFila0) fracMulti0 = fila1[j - 2].multiplicar(fracNega) matrizEcuaciones[saltoFila + 1][j - 1] = str(fila1[j - 2]) matrizEcuaciones[saltoFila + 2][j - 1] = str( fracMulti0.__str__()) fracMulti0 = fracMulti0.sumar(fracFila0) matrizEcuaciones[saltoFila + 3][j - 1] = str( fracFila0.__str__()) matrizEcuaciones[saltoFila + 4][j - 1] = str( fracMulti0.__str__()) nuevaIteracion[iterador][j] = fracMulti0.__str__() multiplicador = str(anteriorIteracion[iterador][col]) if multiplicador[0] == '-': multiplicador[1:len(multiplicador)] else: multiplicador = "-" + multiplicador matrizEcuaciones[saltoFila][0] = anteriorIteracion[iterador][1] + "' = " + \ anteriorIteracion[1][col] + \ "(" + multiplicador + ") + " + \ anteriorIteracion[iterador][1] matrizEcuaciones[ 1 + saltoFila][0] = anteriorIteracion[1][col] + " = " matrizEcuaciones[2 + saltoFila][0] = multiplicador + \ "(" + anteriorIteracion[1][col] + ") = " matrizEcuaciones[ 3 + saltoFila][0] = anteriorIteracion[iterador][1] + " = " matrizEcuaciones[ 4 + saltoFila][0] = anteriorIteracion[iterador][1] + "' = " else: # si no se cumple se guarda la fila 1 donde corresponde for j in range(2, numColumnas, 1): nuevaIteracion[iterador][j] = fila1[j - 2].__str__() # mostrar matriz en la tabla de ecuaciones self.tablaOperaciones.clear() self.tablaOperaciones.setRowCount(numFilaEcuaciones) self.tablaOperaciones.setColumnCount(numColEcuaciones) for j in range(numColEcuaciones): item1 = QTableWidgetItem(" ") self.tablaOperaciones.setHorizontalHeaderItem(j, item1) for row in range(0, numFilaEcuaciones, 1): for colT in range(0, numColEcuaciones, 1): item = QTableWidgetItem(str(matrizEcuaciones[row][colT])) self.tablaOperaciones.setItem(row, colT, item) self.tablaOperaciones.resizeColumnsToContents() # llenar CB y XB for icb in range(2, (numFilas - 2), 1): for ixb in range(0, 2, 1): if icb == fila: nuevaIteracion[fila][ixb] = anteriorIteracion[ixb][col] else: nuevaIteracion[icb][ixb] = anteriorIteracion[icb][ixb] # llenar Zj nuevaIteracion[numFilas - 2][0] = anteriorIteracion[numFilas - 2][0] # " " nuevaIteracion[numFilas - 2][1] = anteriorIteracion[numFilas - 2][1] # "Zj" stringZj = "" acumulaZj = "" for i in range(2, numColumnas, 1): acumulaZj = "" for j in range(2, (numFilas - 2), 1): stringZj = self.guardarZj(str(nuevaIteracion[j][0]), str(nuevaIteracion[j][i])) acumulaZj += stringZj + ";" nuevaIteracion[numFilas - 2][i] = self.devolverZj(acumulaZj) # llenar Cj-Zj nuevaIteracion[numFilas - 1][0] = anteriorIteracion[numFilas - 1][0] # " " nuevaIteracion[numFilas - 1][1] = anteriorIteracion[numFilas - 1][1] # "Zj-Cj" nuevaIteracion[numFilas - 1][numColumnas - 1] = anteriorIteracion[numFilas - 1][numColumnas - 1] # " " stringA = "" stringB = "" for i in range(2, (numColumnas - 1), 1): stringA = str(nuevaIteracion[0][i]) stringB = str(nuevaIteracion[numFilas - 2][i]) nuevaIteracion[numFilas - 1][i] = self.devolverZjCj( stringA, stringB) # mostrar matriz en la tabla self.tablaU.clear() self.tablaU.setRowCount(numFilas) self.tablaOperaciones.setColumnCount(numColumnas) for j in range(numColumnas): item1 = QTableWidgetItem(" ") self.tablaU.setHorizontalHeaderItem(j, item1) for row in range(0, numFilas, 1): for colT in range(0, numColumnas, 1): item = QTableWidgetItem(str(nuevaIteracion[row][colT])) self.tablaU.setItem(row, colT, item) self.tablaU.resizeColumnsToContents() # pintar pivote self.pintarPivote() self.numIteraciones += 1 self.etiquetaIteracion.setText(" " + str(self.numIteraciones)) # Guardar tabla para el pdf fila = self.numRestricciones + 4 columna = self.columSRcompletas + 2 tablaItera = [] for f in range(fila): filaAnterior = [] for c in range(columna): item = self.tablaU.item(f, c).text() filaAnterior.append(item) tablaItera.append(filaAnterior) self.allTable.append(tablaItera) def seguirIteracionesSimplex(self): seSigue = False numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 stringSig = "" siguiente = float(0) claseM = ClaseM.ClaseM(Fraccion.Fraccion(0, 0), "M") fraccionSig = Fraccion.Fraccion(0, 0) for i in range(2, (numColumnas - 2), 1): stringSig = claseM.obtenerValorSinM( self.tablaU.item(numFilas - 1, i).text()) if fraccionSig.posicionBarra(stringSig) == -1: siguiente = float(stringSig) else: fraccionSig = fraccionSig.deTablaFraccion(stringSig) siguiente = fraccionSig.toDecimal() if siguiente > 0: seSigue = True return seSigue def seguirIteracionesBigM(self): seSigue = False numColumnas = self.columSRcompletas + 2 numFilas = self.numRestricciones + 4 stringSig = "" siguiente = float(0) claseM = ClaseM.ClaseM(Fraccion.Fraccion(0, 0), "M") fraccionSig = Fraccion.Fraccion(0, 0) for i in range(2, (numColumnas - 2), 1): stringSig = claseM.obtenerValorSinM( self.tablaU.item(numFilas - 1, i).text()) if fraccionSig.posicionBarra(stringSig) == -1: siguiente = float(stringSig) else: fraccionSig = fraccionSig.deTablaFraccion(stringSig) siguiente = fraccionSig.toDecimal() if siguiente < 0: seSigue = True return seSigue def pintarPivote(self): fila = self.variableSalida() # ubicacion de la variable de salida col = self.variableEntrada() # ubicacion de la variable de entrada pivote = self.tablaU.item(fila, col).text() item = QTableWidgetItem(str(pivote)) item.setBackground(QtGui.QColor(0, 153, 153)) self.tablaU.setItem(fila, col, item) def generarReporte(self): fila = self.numRestricciones + 4 columna = self.columSRcompletas + 2 tituloReporte = "Reporte_" + self.metodo + ".pdf" try: doc = SimpleDocTemplate(tituloReporte, pagesize=A4, topMargin=12) alineacionTitulo = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=20, leading=40) alineacionTituloTabla = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=14, leading=40) alineacionOpTable = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=12, leading=40) alineacionResultados = ParagraphStyle(name="centrar", alignment=TA_LEFT, fontSize=12, leading=30) alineacionRestr = ParagraphStyle(name="centrar", alignment=TA_CENTER, fontSize=12, leading=30) story = [] restriccionesGuardadas = self.guardarRestricciones() resultados = self.guardarResultados() self.guardarRestricciones( ) #guarda solucion optima y el resultados de las variables story.append(Paragraph(self.tituloMetodo, alineacionTitulo)) story.append( Paragraph( f"Función Objetivo: {self.etiquetaFuncionObjetivo.text()}", alineacionResultados)) story.append(Paragraph(f"S.R:", alineacionResultados)) for restr in range(len(restriccionesGuardadas)): story.append( Paragraph(restriccionesGuardadas[restr], alineacionResultados)) solucion = "La solución óptima es Z = " + self.solucion_optima story.append(Paragraph(solucion, alineacionTituloTabla)) variables = "" for iResul in range(len(resultados)): variables += resultados[iResul] story.append(Paragraph(variables, alineacionOpTable)) for table in range(len(self.allTable)): self.arrayFila = [] for f in range(fila): item = self.allTable[table][f] self.arrayFila.append(item) tabla = Table(self.arrayFila, colWidths=50, rowHeights=40) tabla.setStyle([('GRID', (0, 0), (-1, -1), 2, colors.black), ('BOX', (0, 0), (-1, -1), 2, colors.black), ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ('BACKGROUND', (0, 0), (-1, 1), colors.HexColor('#009999')), ('TEXTCOLOR', (0, 0), (-1, 1), colors.HexColor('#ffffff'))]) story.append( Paragraph(f"Iteración #{table}", alineacionTituloTabla)) story.append(tabla) story.append(Spacer(0, 2)) if (table + 1 == len(self.allTable)): story.append(Spacer(0, 0)) else: story.append(Spacer(0, 250)) doc.build(story) msjErr = "Reporte generado correctamente" msgBox5 = QMessageBox() msgBox5.setText(msjErr) msgBox5.setWindowTitle("Éxito") msgBox5.setStyleSheet( "font-size: 14px; font-weight: bold; font-family: Century Gothic" ) msgBox5.exec_() os.system(tituloReporte + "&& exit") except PermissionError: msjErr = "Ocurrió un error al generar el reporte" msgBox6 = QMessageBox() msgBox6.setText(msjErr) msgBox6.setWindowTitle("Error") msgBox6.setStyleSheet( "font-size: 14px; font-weight: bold; font-family: Century Gothic" ) msgBox6.exec_() def guardarResultados(self): resultados = [] columnas = self.columSRcompletas + 2 filas = self.numRestricciones + 4 arregloXBFila = [" "] * (columnas - 3) arregloXBCol = [" "] * self.numRestricciones for i in range(0, len(arregloXBFila), 1): arregloXBFila[i] = self.tablaU.item( 1, (i + 2)).text() #guardo XB Fila for i in range(0, len(arregloXBCol), 1): arregloXBCol[i] = self.tablaU.item((i + 2), 1).text() #guardo XB columna resultados = [" "] * len(arregloXBFila) #ciclo para llenar el arreglo de resultado for i in range(0, len(arregloXBFila), 1): resultados[i] = arregloXBFila[i] + " = 0, " #ciclo para asignar el valor de BI for j in range(0, len(arregloXBCol), 1): if arregloXBFila[i] == arregloXBCol[j]: resultados[ i] = arregloXBFila[i] + " = " + self.tablaU.item( (j + 2), (columnas - 1)).text() + ", " return resultados
class FindAnnotationsDialog(SizePersistedDialog, Logger): GENERIC_STYLE = 'Any style' GENERIC_READER = 'Any reader' def __init__(self, opts): self.matched_ids = set() self.opts = opts self.prefs = opts.prefs super(FindAnnotationsDialog, self).__init__(self.opts.gui, 'find_annotations_dialog') self.setWindowTitle('Find Annotations') self.setWindowIcon(self.opts.icon) self.l = QVBoxLayout(self) self.setLayout(self.l) self.search_criteria_gb = QGroupBox(self) self.search_criteria_gb.setTitle("Search criteria") self.scgl = QGridLayout(self.search_criteria_gb) self.l.addWidget(self.search_criteria_gb) # addWidget(widget, row, col, rowspan, colspan) row = 0 # ~~~~~~~~ Create the Readers comboBox ~~~~~~~~ self.reader_label = QLabel('Reader') self.reader_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.reader_label, row, 0, 1, 1) self.find_annotations_reader_comboBox = QComboBox() self.find_annotations_reader_comboBox.setObjectName('find_annotations_reader_comboBox') self.find_annotations_reader_comboBox.setToolTip('Reader annotations to search for') self.find_annotations_reader_comboBox.addItem(self.GENERIC_READER) racs = ReaderApp.get_reader_app_classes() for ra in sorted(racs.keys()): self.find_annotations_reader_comboBox.addItem(ra) self.scgl.addWidget(self.find_annotations_reader_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Styles comboBox ~~~~~~~~ self.style_label = QLabel('Style') self.style_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.style_label, row, 0, 1, 1) self.find_annotations_color_comboBox = QComboBox() self.find_annotations_color_comboBox.setObjectName('find_annotations_color_comboBox') self.find_annotations_color_comboBox.setToolTip('Annotation style to search for') self.find_annotations_color_comboBox.addItem(self.GENERIC_STYLE) all_colors = COLOR_MAP.keys() all_colors.remove('Default') for color in sorted(all_colors): self.find_annotations_color_comboBox.addItem(color) self.scgl.addWidget(self.find_annotations_color_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Text LineEdit control ~~~~~~~~ self.text_label = QLabel('Text') self.text_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.text_label, row, 0, 1, 1) self.find_annotations_text_lineEdit = MyLineEdit() self.find_annotations_text_lineEdit.setObjectName('find_annotations_text_lineEdit') self.scgl.addWidget(self.find_annotations_text_lineEdit, row, 1, 1, 3) self.reset_text_tb = QToolButton() self.reset_text_tb.setObjectName('reset_text_tb') self.reset_text_tb.setToolTip('Clear search criteria') self.reset_text_tb.setIcon(QIcon(I('trash.png'))) self.reset_text_tb.clicked.connect(self.clear_text_field) self.scgl.addWidget(self.reset_text_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Note LineEdit control ~~~~~~~~ self.note_label = QLabel('Note') self.note_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.note_label, row, 0, 1, 1) self.find_annotations_note_lineEdit = MyLineEdit() self.find_annotations_note_lineEdit.setObjectName('find_annotations_note_lineEdit') self.scgl.addWidget(self.find_annotations_note_lineEdit, row, 1, 1, 3) self.reset_note_tb = QToolButton() self.reset_note_tb.setObjectName('reset_note_tb') self.reset_note_tb.setToolTip('Clear search criteria') self.reset_note_tb.setIcon(QIcon(I('trash.png'))) self.reset_note_tb.clicked.connect(self.clear_note_field) self.scgl.addWidget(self.reset_note_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Date range controls ~~~~~~~~ self.date_range_label = QLabel('Date range') self.date_range_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.scgl.addWidget(self.date_range_label, row, 0, 1, 1) # Date 'From' self.find_annotations_date_from_dateEdit = MyDateEdit(self, datetime(1970,1,1)) self.find_annotations_date_from_dateEdit.setObjectName('find_annotations_date_from_dateEdit') #self.find_annotations_date_from_dateEdit.current_val = datetime(1970,1,1) self.find_annotations_date_from_dateEdit.clear_button.clicked.connect(self.find_annotations_date_from_dateEdit.reset_from_date) self.scgl.addWidget(self.find_annotations_date_from_dateEdit, row, 1, 1, 1) self.scgl.addWidget(self.find_annotations_date_from_dateEdit.clear_button, row, 2, 1, 1) # Date 'To' self.find_annotations_date_to_dateEdit = MyDateEdit(self, datetime.today()) self.find_annotations_date_to_dateEdit.setObjectName('find_annotations_date_to_dateEdit') #self.find_annotations_date_to_dateEdit.current_val = datetime.today() self.find_annotations_date_to_dateEdit.clear_button.clicked.connect(self.find_annotations_date_to_dateEdit.reset_to_date) self.scgl.addWidget(self.find_annotations_date_to_dateEdit, row, 3, 1, 1) self.scgl.addWidget(self.find_annotations_date_to_dateEdit.clear_button, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create a horizontal line ~~~~~~~~ self.hl = QFrame(self) self.hl.setGeometry(QRect(0, 0, 1, 3)) self.hl.setFrameShape(QFrame.HLine) self.hl.setFrameShadow(QFrame.Raised) self.scgl.addWidget(self.hl, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the results label field ~~~~~~~~ self.result_label = QLabel('<p style="color:red">scanning…</p>') self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setWordWrap(False) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.result_label.sizePolicy().hasHeightForWidth()) self.result_label.setSizePolicy(sizePolicy) self.result_label.setMinimumSize(QtCore.QSize(250, 0)) self.scgl.addWidget(self.result_label, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the ButtonBox ~~~~~~~~ self.dialogButtonBox = QDialogButtonBox(self) self.dialogButtonBox.setOrientation(Qt.Horizontal) if False: self.update_button = QPushButton('Update results') self.update_button.setDefault(True) self.update_button.setVisible(False) self.dialogButtonBox.addButton(self.update_button, QDialogButtonBox.ActionRole) self.cancel_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Cancel) self.find_button = self.dialogButtonBox.addButton(self.dialogButtonBox.Ok) self.find_button.setText('Find Matching Books') self.l.addWidget(self.dialogButtonBox) self.dialogButtonBox.clicked.connect(self.find_annotations_dialog_clicked) # ~~~~~~~~ Add a spacer ~~~~~~~~ self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.l.addItem(self.spacerItem) # ~~~~~~~~ Restore previously saved settings ~~~~~~~~ self.restore_settings() # ~~~~~~~~ Declare sizing ~~~~~~~~ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.resize_dialog() # ~~~~~~~~ Connect all signals ~~~~~~~~ self.find_annotations_reader_comboBox.currentIndexChanged.connect(partial(self.update_results, 'reader')) self.find_annotations_color_comboBox.currentIndexChanged.connect(partial(self.update_results, 'color')) self.find_annotations_text_lineEdit.editingFinished.connect(partial(self.update_results, 'text')) self.find_annotations_note_lineEdit.editingFinished.connect(partial(self.update_results, 'note')) # self.connect(self.find_annotations_text_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_text_lineEdit.return_pressed.connect(self.return_pressed) # self.connect(self.find_annotations_note_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_note_lineEdit.return_pressed.connect(self.return_pressed) # Date range signals connected in inventory_available() # ~~~~~~~~ Allow dialog to render before doing inventory ~~~~~~~~ #field = self.prefs.get('cfg_annotations_destination_field', None) field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks(self.opts.gui, field, get_date_range=True) self.annotated_books_scanner.signal.connect(self.inventory_available) QTimer.singleShot(1, self.start_inventory_scan) def clear_note_field(self): if str(self.find_annotations_note_lineEdit.text()) > '': self.find_annotations_note_lineEdit.setText('') self.update_results('clear_note_field') def clear_text_field(self): if str(self.find_annotations_text_lineEdit.text()) > '': self.find_annotations_text_lineEdit.setText('') self.update_results('clear_text_field') def find_annotations_dialog_clicked(self, button): if self.dialogButtonBox.buttonRole(button) == QDialogButtonBox.AcceptRole: self.save_settings() self.accept() elif self.dialogButtonBox.buttonRole(button) == QDialogButtonBox.RejectRole: self.close() def inventory_available(self): ''' Update the Date range widgets with the rounded oldest, newest dates Don't connect date signals until date range available ''' self._log_location() # Reset the date range based on available annotations oldest = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.oldest_annotation)) oldest_day = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.oldest_annotation).replace(hour=0, minute=0, second=0)) newest = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.newest_annotation)) newest_day = QDateTime(datetime.fromtimestamp(self.annotated_books_scanner.newest_annotation).replace(hour=23, minute=59, second=59)) # Set 'From' date limits to inventory values self.find_annotations_date_from_dateEdit.setMinimumDateTime(oldest_day) self.find_annotations_date_from_dateEdit.current_val = oldest self.find_annotations_date_from_dateEdit.setMaximumDateTime(newest_day) # Set 'To' date limits to inventory values self.find_annotations_date_to_dateEdit.setMinimumDateTime(oldest_day) self.find_annotations_date_to_dateEdit.current_val = newest_day self.find_annotations_date_to_dateEdit.setMaximumDateTime(newest_day) # Connect the signals for date range changes self.find_annotations_date_from_dateEdit.dateTimeChanged.connect(partial(self.update_results, 'from_date')) self.find_annotations_date_to_dateEdit.dateTimeChanged.connect(partial(self.update_results, 'to_date')) self.update_results('inventory_available') def restore_settings(self): self.blockSignals(True) ra = self.prefs.get('find_annotations_reader_comboBox', self.GENERIC_READER) ra_index = self.find_annotations_reader_comboBox.findText(ra) self.find_annotations_reader_comboBox.setCurrentIndex(ra_index) color = self.prefs.get('find_annotations_color_comboBox', self.GENERIC_STYLE) color_index = self.find_annotations_color_comboBox.findText(color) self.find_annotations_color_comboBox.setCurrentIndex(color_index) text = self.prefs.get('find_annotations_text_lineEdit', '') self.find_annotations_text_lineEdit.setText(text) note = self.prefs.get('find_annotations_note_lineEdit', '') self.find_annotations_note_lineEdit.setText(note) if False: from_date = self.prefs.get('find_annotations_date_from_dateEdit', datetime(1970,1,1)) self.find_annotations_date_from_dateEdit.current_val = from_date to_date = self.prefs.get('find_annotations_date_to_dateEdit', datetime.today()) self.find_annotations_date_to_dateEdit.current_val = to_date self.blockSignals(False) def return_pressed(self): self.update_results("return_pressed") def save_settings(self): ra = str(self.find_annotations_reader_comboBox.currentText()) self.prefs.set('find_annotations_reader_comboBox', ra) color = str(self.find_annotations_color_comboBox.currentText()) self.prefs.set('find_annotations_color_comboBox', color) text = str(self.find_annotations_text_lineEdit.text()) self.prefs.set('find_annotations_text_lineEdit', text) note = str(self.find_annotations_note_lineEdit.text()) self.prefs.set('find_annotations_note_lineEdit', note) if False: from_date = self.find_annotations_date_from_dateEdit.current_val self.prefs.set('find_annotations_date_from_dateEdit', from_date) to_date = self.find_annotations_date_to_dateEdit.current_val self.prefs.set('find_annotations_date_to_dateEdit', to_date) def start_inventory_scan(self): self._log_location() self.annotated_books_scanner.start() def update_results(self, trigger): #self._log_location(trigger) reader_to_match = str(self.find_annotations_reader_comboBox.currentText()) color_to_match = str(self.find_annotations_color_comboBox.currentText()) text_to_match = str(self.find_annotations_text_lineEdit.text()) note_to_match = str(self.find_annotations_note_lineEdit.text()) from_date = self.find_annotations_date_from_dateEdit.dateTime().toTime_t() to_date = self.find_annotations_date_to_dateEdit.dateTime().toTime_t() annotation_map = self.annotated_books_scanner.annotation_map #field = self.prefs.get("cfg_annotations_destination_field", None) field = get_cc_mapping('annotations', 'field', None) db = self.opts.gui.current_db matched_titles = [] self.matched_ids = set() for cid in annotation_map: mi = db.get_metadata(cid, index_is_id=True) soup = None if field == 'Comments': if mi.comments: soup = BeautifulSoup(mi.comments) else: if mi.get_user_metadata(field, False)['#value#'] is not None: soup = BeautifulSoup(mi.get_user_metadata(field, False)['#value#']) if soup: uas = soup.findAll('div', 'annotation') for ua in uas: # Are we already logged? if cid in self.matched_ids: continue # Check reader if reader_to_match != self.GENERIC_READER: this_reader = ua['reader'] if this_reader != reader_to_match: continue # Check color if color_to_match != self.GENERIC_STYLE: this_color = ua.find('table')['color'] if this_color != color_to_match: continue # Check date range, allow for mangled timestamp try: timestamp = float(ua.find('td', 'timestamp')['uts']) if timestamp < from_date or timestamp > to_date: continue except: continue highlight_text = '' try: pels = ua.findAll('p', 'highlight') for pel in pels: highlight_text += pel.string + '\n' except: pass if text_to_match > '': if not re.search(text_to_match, highlight_text, flags=re.IGNORECASE): continue note_text = '' try: nels = ua.findAll('p', 'note') for nel in nels: note_text += nel.string + '\n' except: pass if note_to_match > '': if not re.search(note_to_match, note_text, flags=re.IGNORECASE): continue # If we made it this far, add the id to matched_ids self.matched_ids.add(cid) matched_titles.append(mi.title) # Update the results box matched_titles.sort() if len(annotation_map): if len(matched_titles): first_match = ("<i>%s</i>" % matched_titles[0]) if len(matched_titles) == 1: results = first_match else: results = first_match + (" and %d more." % (len(matched_titles) - 1)) self.result_label.setText('<p style="color:blue">{0}</p>'.format(results)) else: self.result_label.setText('<p style="color:red">no matches</p>') else: self.result_label.setText('<p style="color:red">no annotated books in library</p>') self.resize_dialog()
class RemoveDialog(Dialog): def __init__(self, parent): from calibre_plugins.diaps_toolbag.span_div_config import plugin_prefs as prefs self.criteria = None self.prefs = prefs self.parent = parent self.help_file_name = '{0}_span_div_help.html'.format(PLUGIN_SAFE_NAME) self.taglist = TAGLIST Dialog.__init__(self, _('Edit Spans & Divs'), 'toolbag_spans_divs_dialog', parent) def setup_ui(self): DELETE_STR = _('Delete') MODIFY_STR = _('Modify') NO_ATTRIB_STR = _('No attributes ("naked" tag)') self.NO_CHANGE_STR = _('No change') layout = QVBoxLayout(self) self.setLayout(layout) help_layout = QHBoxLayout() layout.addLayout(help_layout) # Add hyperlink to a help file at the right. We will replace the correct name when it is clicked. help_label = QLabel('<a href="http://www.foo.com/">Plugin Help</a>', self) help_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard) help_label.setAlignment(Qt.AlignRight) help_label.linkActivated.connect(self.help_link_activated) help_layout.addWidget(help_label) action_layout = QHBoxLayout() layout.addLayout(action_layout) label = QLabel(_('Action type:'), self) action_layout.addWidget(label) self.action_combo = QComboBox() action_layout.addWidget(self.action_combo) self.action_combo.addItems([DELETE_STR, MODIFY_STR]) self.action_combo.currentIndexChanged.connect(self.update_gui) tag_layout = QHBoxLayout() layout.addLayout(tag_layout) label = QLabel(_('Tag name:'), self) tag_layout.addWidget(label) self.tag_combo = QComboBox() tag_layout.addWidget(self.tag_combo) self.tag_combo.addItems(self.taglist) self.tag_combo.currentIndexChanged.connect(self.update_gui) attr_layout = QHBoxLayout() layout.addLayout(attr_layout) label = QLabel(_('Having the attribute:'), self) attr_layout.addWidget(label) self.attr_combo = QComboBox() attr_layout.addWidget(self.attr_combo) self.attr_combo.addItems(self.prefs['attrs']) self.attr_combo.addItem(NO_ATTRIB_STR) self.attr_combo.currentIndexChanged.connect(self.update_gui) srch_layout = QHBoxLayout() layout.addLayout(srch_layout) label = QLabel(_("Whose value is (no quotes):"), self) srch_layout.addWidget(label) self.srch_txt = QLineEdit('', self) srch_layout.addWidget(self.srch_txt) self.srch_method = QCheckBox(_('Regex'), self) srch_layout.addWidget(self.srch_method) newtag_layout = QHBoxLayout() layout.addLayout(newtag_layout) label = QLabel(_('Change tag to:'), self) newtag_layout.addWidget(label) self.newtag_combo = QComboBox() newtag_layout.addWidget(self.newtag_combo) self.newtag_combo.addItem(self.NO_CHANGE_STR) self.newtag_combo.addItems(self.prefs['{}_changes'.format(unicode(self.tag_combo.currentText()))]) if self.action_combo.currentIndex() == 0: self.newtag_combo.setDisabled(True) newattr_layout = QVBoxLayout() layout.addLayout(newattr_layout) label = QLabel(_('New attribute string to insert (entire):'), self) newattr_layout.addWidget(label) self.newattr_txt = QLineEdit('', self) newattr_layout.addWidget(self.newattr_txt) self.copy_attr = QCheckBox(_('Copy existing attribute string'), self) self.copy_attr.stateChanged.connect(self.update_txt_box) newattr_layout.addWidget(self.copy_attr) if self.action_combo.currentIndex() == 0: self.copy_attr.setDisabled(True) self.newattr_txt.setDisabled(True) layout.addSpacing(10) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self._ok_clicked) button_box.rejected.connect(self.reject) layout.addWidget(button_box) def update_gui(self): if self.attr_combo.currentIndex() == self.attr_combo.count()-1: self.srch_txt.clear() self.srch_txt.setDisabled(True) self.srch_method.setChecked(False) self.srch_method.setDisabled(True) else: self.srch_txt.setDisabled(False) self.srch_method.setDisabled(False) self.newtag_combo.clear() self.newtag_combo.addItem(self.NO_CHANGE_STR) self.newtag_combo.addItems(self.prefs['{}_changes'.format(unicode(self.tag_combo.currentText()))]) if self.action_combo.currentIndex() == 0: self.newtag_combo.setCurrentIndex(0) self.newtag_combo.setDisabled(True) self.newattr_txt.clear() self.newattr_txt.setDisabled(True) self.copy_attr.setChecked(False) self.copy_attr.setDisabled(True) else: self.newtag_combo.setDisabled(False) self.newattr_txt.setDisabled(False) self.copy_attr.setDisabled(False) def update_txt_box(self): if self.copy_attr.isChecked(): self.newattr_txt.clear() self.newattr_txt.setDisabled(True) else: self.newattr_txt.setDisabled(False) def _ok_clicked(self): if self.action_combo.currentIndex() == 0: action = 'delete' else: action = 'modify' if self.attr_combo.currentIndex() == self.attr_combo.count()-1: attribute = None else: attribute = unicode(self.attr_combo.currentText()) srch_str = unicode(self.srch_txt.displayText()) if not len(srch_str): srch_str = None if srch_str is None and attribute is not None: return error_dialog(self.parent, _('Error'), '<p>{0}'.format( _('Must enter a value for the attribute selected')), det_msg='', show=True) srch_method = 'normal' if self.srch_method.isChecked(): srch_method = 'regex' if self.newtag_combo.currentIndex() == 0: newtag = None else: newtag = unicode(self.newtag_combo.currentText()) if action == 'modify' and newtag is None and self.copy_attr.isChecked(): return error_dialog(self.parent, _('Error'), '<p>{0}'.format( _('What--exactly--would that achieve?')), det_msg='', show=True) new_str = unicode(self.newattr_txt.displayText()) copy_attr = False if self.copy_attr.isChecked(): copy_attr = True if not len(new_str): new_str = '' self.criteria = (srch_str, srch_method, unicode(self.tag_combo.currentText()), attribute, action, newtag, new_str, copy_attr) self.accept() def getCriteria(self): return self.criteria def help_link_activated(self, url): def get_help_file_resource(): # Copy the HTML helpfile to the plugin directory each time the # link is clicked in case the helpfile is updated in newer plugins. file_path = os.path.join(config_dir, 'plugins', self.help_file_name) with open(file_path,'w') as f: f.write(load_resource('resources/{}'.format(self.help_file_name))) return file_path url = 'file:///' + get_help_file_resource() open_url(QUrl(url))
class RuleEditor(QDialog): # {{{ @property def doing_multiple(self): return hasattr(self, 'multiple_icon_cb') and self.multiple_icon_cb.isChecked() def __init__(self, fm, pref_name, parent=None): QDialog.__init__(self, parent) self.fm = fm if pref_name == 'column_color_rules': self.rule_kind = 'color' rule_text = _('column coloring') elif pref_name == 'column_icon_rules': self.rule_kind = 'icon' rule_text = _('column icon') elif pref_name == 'cover_grid_icon_rules': self.rule_kind = 'emblem' rule_text = _('Cover grid emblem') self.setWindowIcon(QIcon(I('format-fill-color.png'))) self.setWindowTitle(_('Create/edit a {0} rule').format(rule_text)) self.l = l = QGridLayout(self) self.setLayout(l) self.l1 = l1 = QLabel(_('Create a {0} rule by' ' filling in the boxes below').format(rule_text)) l.addWidget(l1, 0, 0, 1, 8) self.f1 = QFrame(self) self.f1.setFrameShape(QFrame.HLine) l.addWidget(self.f1, 1, 0, 1, 8) self.l2 = l2 = QLabel(_('Add the emblem:') if self.rule_kind == 'emblem' else _('Set the')) l.addWidget(l2, 2, 0) if self.rule_kind == 'color': l.addWidget(QLabel(_('color'))) elif self.rule_kind == 'icon': self.kind_box = QComboBox(self) for tt, t in icon_rule_kinds: self.kind_box.addItem(tt, t) l.addWidget(self.kind_box, 2, 1) self.kind_box.setToolTip(textwrap.fill(_( 'If you choose composed icons and multiple rules match, then all the' ' matching icons will be combined, otherwise the icon from the' ' first rule to match will be used.'))) else: pass self.l3 = l3 = QLabel(_('of the column:')) l.addWidget(l3, 2, 2) self.column_box = QComboBox(self) l.addWidget(self.column_box, 2, 3) self.l4 = l4 = QLabel(_('to')) l.addWidget(l4, 2, 4) if self.rule_kind == 'emblem': l3.setVisible(False), self.column_box.setVisible(False), l4.setVisible(False) def create_filename_box(): self.filename_box = f = QComboBox() self.filenamebox_view = v = QListView() v.setIconSize(QSize(32, 32)) self.filename_box.setView(v) self.orig_filenamebox_view = f.view() f.setMinimumContentsLength(20), f.setSizeAdjustPolicy(f.AdjustToMinimumContentsLengthWithIcon) self.populate_icon_filenames() if self.rule_kind == 'color': self.color_box = ColorButton(parent=self) self.color_label = QLabel('Sample text Sample text') self.color_label.setTextFormat(Qt.RichText) l.addWidget(self.color_box, 2, 5) l.addWidget(self.color_label, 2, 6) l.addItem(QSpacerItem(10, 10, QSizePolicy.Expanding), 2, 7) elif self.rule_kind == 'emblem': create_filename_box() self.update_filename_box() self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add new image')) l.addWidget(self.filename_box) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('(Images should be square-ish)')), 2, 7) l.setColumnStretch(7, 10) else: create_filename_box() vb = QVBoxLayout() self.multiple_icon_cb = QCheckBox(_('Choose &more than one icon')) vb.addWidget(self.multiple_icon_cb) self.update_filename_box() self.multiple_icon_cb.clicked.connect(self.multiple_box_clicked) vb.addWidget(self.filename_box) l.addLayout(vb, 2, 5) self.filename_button = QPushButton(QIcon(I('document_open.png')), _('&Add icon')) l.addWidget(self.filename_button, 2, 6) l.addWidget(QLabel(_('Icons should be square or landscape')), 2, 7) l.setColumnStretch(7, 10) self.l5 = l5 = QLabel( _('Only if the following conditions are all satisfied:')) l.addWidget(l5, 3, 0, 1, 7) self.scroll_area = sa = QScrollArea(self) sa.setMinimumHeight(300) sa.setMinimumWidth(950) sa.setWidgetResizable(True) l.addWidget(sa, 4, 0, 1, 8) self.add_button = b = QPushButton(QIcon(I('plus.png')), _('Add &another condition')) l.addWidget(b, 5, 0, 1, 8) b.clicked.connect(self.add_blank_condition) self.l6 = l6 = QLabel(_('You can disable a condition by' ' blanking all of its boxes')) l.addWidget(l6, 6, 0, 1, 8) self.bb = bb = QDialogButtonBox( QDialogButtonBox.Ok|QDialogButtonBox.Cancel) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) l.addWidget(bb, 7, 0, 1, 8) if self.rule_kind != 'color': self.remove_button = b = bb.addButton(_('&Remove icon'), bb.ActionRole) b.setIcon(QIcon(I('minus.png'))) b.setMenu(QMenu()) b.setToolTip('<p>' + _('Remove a previously added icon. Note that doing so will cause rules that use it to stop working.')) self.update_remove_button() self.conditions_widget = QWidget(self) sa.setWidget(self.conditions_widget) self.conditions_widget.setLayout(QVBoxLayout()) self.conditions_widget.layout().setAlignment(Qt.AlignTop) self.conditions = [] if self.rule_kind == 'color': for b in (self.column_box, ): b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setMinimumContentsLength(15) for key in sorted(displayable_columns(fm), key=lambda k: sort_key(fm[k]['name']) if k != color_row_key else 0): if key == color_row_key and self.rule_kind != 'color': continue name = all_columns_string if key == color_row_key else fm[key]['name'] if name: self.column_box.addItem(name, key) self.column_box.setCurrentIndex(0) if self.rule_kind == 'color': self.color_box.color = '#000' self.update_color_label() self.color_box.color_changed.connect(self.update_color_label) else: self.rule_icon_files = [] self.filename_button.clicked.connect(self.filename_button_clicked) self.resize(self.sizeHint()) def multiple_box_clicked(self): self.update_filename_box() self.update_icon_filenames_in_box() @property def icon_folder(self): return os.path.join(config_dir, 'cc_icons') def populate_icon_filenames(self): d = self.icon_folder self.icon_file_names = [] if os.path.exists(d): for icon_file in os.listdir(d): icon_file = lower(icon_file) if os.path.exists(os.path.join(d, icon_file)) and icon_file.endswith('.png'): self.icon_file_names.append(icon_file) self.icon_file_names.sort(key=sort_key) def update_filename_box(self): doing_multiple = self.doing_multiple model = QStandardItemModel() self.filename_box.setModel(model) self.icon_file_names.sort(key=sort_key) if doing_multiple: item = QStandardItem(_('Open to see checkboxes')) item.setIcon(QIcon(I('blank.png'))) else: item = QStandardItem('') item.setFlags(Qt.ItemFlag(0)) model.appendRow(item) for i,filename in enumerate(self.icon_file_names): item = QStandardItem(filename) if doing_multiple: item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) item.setData(Qt.Unchecked, Qt.CheckStateRole) else: item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) icon = QIcon(os.path.join(self.icon_folder, filename)) item.setIcon(icon) model.appendRow(item) def update_color_label(self): pal = QApplication.palette() bg1 = unicode_type(pal.color(pal.Base).name()) bg2 = unicode_type(pal.color(pal.AlternateBase).name()) c = self.color_box.color self.color_label.setText(''' <span style="color: {c}; background-color: {bg1}"> {st} </span> <span style="color: {c}; background-color: {bg2}"> {st} </span> '''.format(c=c, bg1=bg1, bg2=bg2, st=_('Sample text'))) def sanitize_icon_file_name(self, icon_path): n = lower(sanitize_file_name_unicode( os.path.splitext( os.path.basename(icon_path))[0]+'.png')) return n.replace("'", '_') def filename_button_clicked(self): try: path = choose_files(self, 'choose_category_icon', _('Select Icon'), filters=[ (_('Images'), ['png', 'gif', 'jpg', 'jpeg'])], all_files=False, select_only_single_file=True) if path: icon_path = path[0] icon_name = self.sanitize_icon_file_name(icon_path) if icon_name not in self.icon_file_names: self.icon_file_names.append(icon_name) try: p = QIcon(icon_path).pixmap(QSize(128, 128)) d = self.icon_folder if not os.path.exists(os.path.join(d, icon_name)): if not os.path.exists(d): os.makedirs(d) with open(os.path.join(d, icon_name), 'wb') as f: f.write(pixmap_to_data(p, format='PNG')) except: import traceback traceback.print_exc() self.update_filename_box() self.update_remove_button() if self.doing_multiple: if icon_name not in self.rule_icon_files: self.rule_icon_files.append(icon_name) self.update_icon_filenames_in_box() else: self.filename_box.setCurrentIndex(self.filename_box.findText(icon_name)) self.filename_box.adjustSize() except: import traceback traceback.print_exc() return def get_filenames_from_box(self): if self.doing_multiple: model = self.filename_box.model() fnames = [] for i in range(1, model.rowCount()): item = model.item(i, 0) if item.checkState() == Qt.Checked: fnames.append(lower(unicode_type(item.text()))) fname = ' : '.join(fnames) else: fname = lower(unicode_type(self.filename_box.currentText())) return fname def update_icon_filenames_in_box(self): if self.rule_icon_files: if not self.doing_multiple: idx = self.filename_box.findText(self.rule_icon_files[0]) if idx >= 0: self.filename_box.setCurrentIndex(idx) else: self.filename_box.setCurrentIndex(0) else: model = self.filename_box.model() for icon in self.rule_icon_files: idx = self.filename_box.findText(icon) if idx >= 0: item = model.item(idx) item.setCheckState(Qt.Checked) def update_remove_button(self): m = self.remove_button.menu() m.clear() for name in self.icon_file_names: ac = m.addAction(QIcon(os.path.join(self.icon_folder, name)), name) connect_lambda(ac.triggered, self, lambda self: self.remove_image(self.sender().text())) def remove_image(self, name): try: os.remove(os.path.join(self.icon_folder, name)) except EnvironmentError: pass else: self.populate_icon_filenames() self.update_remove_button() self.update_filename_box() self.update_icon_filenames_in_box() def add_blank_condition(self): c = ConditionEditor(self.fm, parent=self.conditions_widget) self.conditions.append(c) self.conditions_widget.layout().addWidget(c) def apply_rule(self, kind, col, rule): if kind == 'color': if rule.color: self.color_box.color = rule.color else: if self.rule_kind == 'icon': for i, tup in enumerate(icon_rule_kinds): if kind == tup[1]: self.kind_box.setCurrentIndex(i) break self.rule_icon_files = [ic.strip() for ic in rule.color.split(':')] if len(self.rule_icon_files) > 1: self.multiple_icon_cb.setChecked(True) self.update_filename_box() self.update_icon_filenames_in_box() for i in range(self.column_box.count()): c = unicode_type(self.column_box.itemData(i) or '') if col == c: self.column_box.setCurrentIndex(i) break for c in rule.conditions: ce = ConditionEditor(self.fm, parent=self.conditions_widget) self.conditions.append(ce) self.conditions_widget.layout().addWidget(ce) try: ce.condition = c except: import traceback traceback.print_exc() def accept(self): if self.rule_kind != 'color': fname = self.get_filenames_from_box() if not fname: error_dialog(self, _('No icon selected'), _('You must choose an icon for this rule'), show=True) return if self.validate(): QDialog.accept(self) def validate(self): r = Rule(self.fm) for c in self.conditions: condition = c.condition if condition is not None: try: r.add_condition(*condition) except Exception as e: import traceback error_dialog(self, _('Invalid condition'), _('One of the conditions for this rule is' ' invalid: <b>%s</b>')%e, det_msg=traceback.format_exc(), show=True) return False if len(r.conditions) < 1: error_dialog(self, _('No conditions'), _('You must specify at least one non-empty condition' ' for this rule'), show=True) return False return True @property def rule(self): r = Rule(self.fm) if self.rule_kind != 'color': r.color = self.get_filenames_from_box() else: r.color = self.color_box.color idx = self.column_box.currentIndex() col = unicode_type(self.column_box.itemData(idx) or '') for c in self.conditions: condition = c.condition if condition is not None: r.add_condition(*condition) if self.rule_kind == 'icon': kind = unicode_type(self.kind_box.itemData( self.kind_box.currentIndex()) or '') else: kind = self.rule_kind return kind, col, r
class UArmUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(UArmUI, self).__init__() self.handler = UArmHandler(self) self.lang = self.main_ui.lang self.status = 0 self.set_ui() self.set_disable(True) def set_ui(self): self._set_common_top_ui() self._set_tab() self._set_common_down_ui() self.connect_slot() def _set_common_top_ui(self): top_frame = QFrame() top_frame.setMaximumHeight(60) top_layout = QVBoxLayout(top_frame) self.layout.addWidget(top_frame) common_top_frame = QFrame() common_top_frame.setMinimumHeight(50) common_top_frame.setMaximumHeight(50) common_top_layout = QHBoxLayout(common_top_frame) top_layout.addWidget(common_top_frame) common_top_layout.addStretch(0) label = QLabel(i18n[self.lang]['Type'] + ':') self.label_type = QLabel('') self.label_type.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_type) label = QLabel(i18n[self.lang]['Mode'] + ':') self.label_mode = QLabel('') self.label_mode.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_mode) label = QLabel(i18n[self.lang]['HardwareVersion'] + ':') self.label_hard_version = QLabel('') self.label_hard_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_hard_version) label = QLabel(i18n[self.lang]['FirmwareVersion'] + ':') self.label_firm_version = QLabel('') self.label_firm_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_firm_version) label_1 = QLabel(i18n[self.lang]['Connected'] + ':') self.label_connected = QLabel() img = QImage() self.label_connected.setMaximumHeight(20) self.label_connected.setMaximumWidth(20) self.label_connected.setScaledContents(True) if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.lnt_addr = QLineEdit('COM12') self.lnt_addr.setMaximumWidth(50) self.lnt_addr.setMinimumWidth(30) self.btn_connect = QPushButton(i18n[self.lang]['Connect']) # self.btn_connect.setMaximumWidth(50) # common_top_layout.addStretch(0) common_top_layout.setSpacing(10) common_top_layout.addWidget(label_1) common_top_layout.addWidget(self.label_connected) common_top_layout.addWidget(self.lnt_addr) common_top_layout.addWidget(self.btn_connect) def _set_common_down_ui(self): slider_frame = QFrame() slider_layout = QGridLayout(slider_frame) self.layout.addWidget(slider_frame) label = QLabel(i18n[self.lang]['Speed'] + ':') self.slider_speed = QSlider(Qt.Horizontal) self.spinbox_speed = QSpinBox() self.slider_speed.setMinimum(1) self.slider_speed.setMaximum(100000) self.slider_speed.setValue(10000) self.spinbox_speed.setSingleStep(1) self.spinbox_speed.setMinimum(1) self.spinbox_speed.setMaximum(100000) self.spinbox_speed.setValue(10000) slider_layout.addWidget(label, 0, 0) slider_layout.addWidget(self.slider_speed, 0, 1) slider_layout.addWidget(self.spinbox_speed, 0, 2) # label = QLabel(i18n[self.lang]['Acc'] + ':') # self.slider_acc = QSlider(Qt.Horizontal) # self.spinbox_acc = QSpinBox() # self.slider_acc.setMinimum(1) # self.slider_acc.setMaximum(100000) # self.slider_acc.setValue(5000) # self.spinbox_acc.setSingleStep(1) # self.spinbox_acc.setMinimum(1) # self.spinbox_acc.setMaximum(100000) # self.spinbox_acc.setValue(5000) # slider_layout.addWidget(label, 0, 3) # slider_layout.addWidget(self.slider_acc, 0, 4) # slider_layout.addWidget(self.spinbox_acc, 0, 5) btn_frame = QFrame() btn_layout = QGridLayout(btn_frame) self.layout.addWidget(btn_frame) self.btn_get_device_info = QPushButton(i18n[self.lang]['GetDeviceInfo']) self.btn_get_position = QPushButton(i18n[self.lang]['GetPosition']) self.btn_get_polar = QPushButton(i18n[self.lang]['GetPolar']) self.btn_get_servo_angle = QPushButton(i18n[self.lang]['GetServoAngle']) self.btn_get_mode = QPushButton(i18n[self.lang]['GetMode']) btn_layout.addWidget(self.btn_get_device_info, 0, 0) btn_layout.addWidget(self.btn_get_position, 0, 1) btn_layout.addWidget(self.btn_get_polar, 0, 2) btn_layout.addWidget(self.btn_get_servo_angle, 0, 3) btn_layout.addWidget(self.btn_get_mode, 0, 4) self.combobox_servo = QComboBox() self.combobox_servo.setStyleSheet('''color: blue;''') for item in ['axis-1', 'axis-2', 'axis-3', 'axis-all']: self.combobox_servo.addItem(item) self.combobox_servo.setCurrentIndex(0) btn_layout.addWidget(self.combobox_servo, 0, 0) self.btn_servo_attach = QPushButton(i18n[self.lang]['ServoAttach']) self.btn_servo_detach = QPushButton(i18n[self.lang]['ServoDetach']) self.combobox_mode = QComboBox() self.combobox_mode.setStyleSheet('''color: blue;''') for item in ['normal', 'laser', '3D', 'pen']: self.combobox_mode.addItem(item) self.combobox_mode.setCurrentIndex(0) self.btn_set_mode = QPushButton(i18n[self.lang]['SetMode']) btn_layout.addWidget(self.combobox_servo, 1, 0) btn_layout.addWidget(self.btn_servo_attach, 1, 1) btn_layout.addWidget(self.btn_servo_detach, 1, 2) btn_layout.addWidget(self.combobox_mode, 1, 3) btn_layout.addWidget(self.btn_set_mode, 1, 4) self.btn_reset = QPushButton(i18n[self.lang]['Reset']) self.btn_pump_on = QPushButton(i18n[self.lang]['PumpOn']) self.btn_pump_off = QPushButton(i18n[self.lang]['PumpOff']) self.btn_gripper_catch = QPushButton(i18n[self.lang]['GripperCatch']) self.btn_gripper_release = QPushButton(i18n[self.lang]['GripperRelease']) btn_layout.addWidget(self.btn_reset, 2, 0) btn_layout.addWidget(self.btn_pump_on, 2, 1) btn_layout.addWidget(self.btn_pump_off, 2, 2) btn_layout.addWidget(self.btn_gripper_catch, 2, 3) btn_layout.addWidget(self.btn_gripper_release, 2, 4) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def connect_slot(self): self.btn_connect.clicked.connect(self.connect) self.slider_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_speed, scale=1)) self.spinbox_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_speed, scale=1)) # self.slider_acc.valueChanged.connect( # functools.partial(self.slider_spinbox_related, slave=self.spinbox_acc, scale=1)) # self.spinbox_acc.valueChanged.connect( # functools.partial(self.slider_spinbox_related, slave=self.slider_acc, scale=1)) self.btn_get_device_info.clicked.connect(self.get_device_info) self.btn_get_position.clicked.connect(self.get_position) self.btn_get_polar.clicked.connect(self.get_polar) self.btn_get_servo_angle.clicked.connect(self.get_servo_angle) self.btn_get_mode.clicked.connect(self.get_mode) self.btn_servo_attach.clicked.connect(self.set_servo_attach) self.btn_servo_detach.clicked.connect(self.set_servo_detach) self.btn_set_mode.clicked.connect(self.set_mode) self.btn_reset.clicked.connect(self.reset) self.btn_pump_on.clicked.connect(self.pump_on) self.btn_pump_off.clicked.connect(self.pump_off) self.btn_gripper_catch.clicked.connect(self.gripper_catch) self.btn_gripper_release.clicked.connect(self.gripper_release) def reset_flag(self): self.cartesian_ui.reset_flag() self.axis_ui.reset_flag() def update_connect_status(self, item): try: img = QImage() if item and self.status != 1: self.status = 1 logger.info('connect to {} success'.format(self.handler.port)) if img.load(connect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Disconnect']) self.btn_connect.setStyleSheet('''color: red;font:bold;''') self.set_disable(False) elif not item and self.status != 0: self.status = 0 logger.info('disconnect from {0} or failed connect {0}'.format(self.handler.port)) self.handler.cmd_que.queue.clear() if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') self.set_disable(True) except Exception as e: print(e) def connect(self): try: if str(self.btn_connect.text()) == i18n[self.lang]['Connect']: addr = self.lnt_addr.text().strip() if addr == 'auto': addr = None self.btn_connect.setText('Connecting') self.status = 2 self.btn_connect.setStyleSheet('''color: orange;font:bold;''') self.handler.connect(addr) # if self.window.connect(addr, report_type=report_type): # self.btn_connect.setText(self.disconnect_label) # self.btn_connect.setStyleSheet('''color: red;font:bold;''') elif str(self.btn_connect.text()) == i18n[self.lang]['Disconnect']: self.handler.disconnect() self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def get_device_info(self, event): try: item = { 'cmd': 'get_device_info', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_mode(self, event): try: item = { 'cmd': 'get_mode', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_position(self, event): try: item = { 'cmd': 'get_position', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_polar(self, event): try: item = { 'cmd': 'get_polar', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_servo_angle(self, event): try: item = { 'cmd': 'get_servo_angle', } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_attach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = None else: servo_id = int(self.combobox_servo.currentIndex()) item = { 'cmd': 'set_servo_attach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_detach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = None else: servo_id = int(self.combobox_servo.currentIndex()) item = { 'cmd': 'set_servo_detach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def pump_on(self, event): try: item = { 'cmd': 'set_pump', 'kwargs': { 'on': True } } self.handler.put_cmd_que(item) except Exception as e: print(e) def pump_off(self, event): try: item = { 'cmd': 'set_pump', 'kwargs': { 'on': False } } self.handler.put_cmd_que(item) except Exception as e: print(e) def gripper_catch(self, event): try: item = { 'cmd': 'set_gripper', 'kwargs': { 'catch': True } } self.handler.put_cmd_que(item) except Exception as e: print(e) def gripper_release(self, event): try: item = { 'cmd': 'set_gripper', 'kwargs': { 'catch': False } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_mode(self, event): try: mode = self.combobox_mode.currentIndex() item = { 'cmd': 'set_mode', 'kwargs': { 'mode': int(mode) } } self.handler.put_cmd_que(item) except Exception as e: print(e) def reset(self, event): try: self.handler.cmd_que.queue.clear() item = { 'cmd': 'reset', 'kwargs': { 'speed': self.spinbox_speed.value(), 'wait': False, } } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def _set_tab(self): tab_widget = QTabWidget() tab_widget.setMaximumHeight(self.main_ui.window.geometry().height() // 2) self.layout.addWidget(tab_widget) toolBox1 = QToolBox() toolBox2 = QToolBox() groupBox1 = QGroupBox() groupBox2 = QGroupBox() toolBox1.addItem(groupBox1, "") toolBox2.addItem(groupBox2, "") tab_widget.addTab(toolBox1, i18n[self.lang]['Angle']) tab_widget.addTab(toolBox2, i18n[self.lang]['Coordinate']) joint_layout = QVBoxLayout(groupBox1) cartesian_layout = QVBoxLayout(groupBox2) self.cartesian_ui = CoordinateUI(self, cartesian_layout) self.axis_ui = AngleUI(self, joint_layout) def update_device_info(self, device_info): if device_info is not None: self.label_type.setText(str(device_info.get('device_type', None))) self.label_hard_version.setText(str(device_info.get('hardware_version', None))) self.label_firm_version.setText(str(device_info.get('firmware_version', None))) def update_mode(self, mode): if mode is not None: if mode == 0: mode_str = 'Normal' elif mode == 1: mode_str = 'Laser' elif mode == 2: mode_str = '3D' elif mode == 3: mode_str = 'Pen' else: mode_str = self.label_mode.text() self.label_mode.setText(mode_str) def set_disable(self, disable): try: self.btn_get_device_info.setDisabled(disable) self.btn_get_position.setDisabled(disable) self.btn_get_polar.setDisabled(disable) self.btn_get_servo_angle.setDisabled(disable) self.btn_get_mode.setDisabled(disable) self.combobox_servo.setDisabled(disable) self.combobox_mode.setDisabled(disable) self.btn_servo_attach.setDisabled(disable) self.btn_servo_detach.setDisabled(disable) self.btn_reset.setDisabled(disable) self.btn_pump_on.setDisabled(disable) self.btn_pump_off.setDisabled(disable) self.btn_gripper_catch.setDisabled(disable) self.btn_gripper_release.setDisabled(disable) self.slider_speed.setDisabled(disable) self.spinbox_speed.setDisabled(disable) # self.slider_acc.setDisabled(disable) # self.spinbox_acc.setDisabled(disable) self.axis_ui.set_disable(disable) self.cartesian_ui.set_disable(disable) except Exception as e: print(e)
class InsertSemantics(Dialog): def __init__(self, container, parent=None): self.container = container self.anchor_cache = {} self.original_type_map = {item.get('type', ''):(container.href_to_name(item.get('href'), container.opf_name), item.get('href', '').partition('#')[-1]) for item in container.opf_xpath('//opf:guide/opf:reference[@href and @type]')} self.final_type_map = self.original_type_map.copy() self.create_known_type_map() Dialog.__init__(self, _('Set Semantics'), 'insert-semantics', parent=parent) def sizeHint(self): return QSize(800, 600) def create_known_type_map(self): _ = lambda x: x self.known_type_map = { 'title-page': _('Title Page'), 'toc': _('Table of Contents'), 'index': _('Index'), 'glossary': _('Glossary'), 'acknowledgements': _('Acknowledgements'), 'bibliography': _('Bibliography'), 'colophon': _('Colophon'), 'copyright-page': _('Copyright page'), 'dedication': _('Dedication'), 'epigraph': _('Epigraph'), 'foreword': _('Foreword'), 'loi': _('List of Illustrations'), 'lot': _('List of Tables'), 'notes': _('Notes'), 'preface': _('Preface'), 'text': _('Text'), } _ = __builtins__['_'] type_map_help = { 'title-page': _('Page with title, author, publisher, etc.'), 'index': _('Back-of-book style index'), 'text': _('First "real" page of content'), } t = _ all_types = [(k, (('%s (%s)' % (t(v), type_map_help[k])) if k in type_map_help else t(v))) for k, v in self.known_type_map.iteritems()] all_types.sort(key=lambda x: sort_key(x[1])) self.all_types = OrderedDict(all_types) def setup_ui(self): self.l = l = QVBoxLayout(self) self.setLayout(l) self.tl = tl = QFormLayout() self.semantic_type = QComboBox(self) for key, val in self.all_types.iteritems(): self.semantic_type.addItem(val, key) tl.addRow(_('Type of &semantics:'), self.semantic_type) self.target = t = QLineEdit(self) t.setPlaceholderText(_('The destination (href) for the link')) tl.addRow(_('&Target:'), t) l.addLayout(tl) self.hline = hl = QFrame(self) hl.setFrameStyle(hl.HLine) l.addWidget(hl) self.h = h = QHBoxLayout() l.addLayout(h) names = [n for n, linear in self.container.spine_names] fn, f = create_filterable_names_list(names, filter_text=_('Filter files'), parent=self) self.file_names, self.file_names_filter = fn, f fn.selectionModel().selectionChanged.connect(self.selected_file_changed) self.fnl = fnl = QVBoxLayout() self.la1 = la = QLabel(_('Choose a &file:')) la.setBuddy(fn) fnl.addWidget(la), fnl.addWidget(f), fnl.addWidget(fn) h.addLayout(fnl), h.setStretch(0, 2) fn, f = create_filterable_names_list([], filter_text=_('Filter locations'), parent=self) self.anchor_names, self.anchor_names_filter = fn, f fn.selectionModel().selectionChanged.connect(self.update_target) fn.doubleClicked.connect(self.accept, type=Qt.QueuedConnection) self.anl = fnl = QVBoxLayout() self.la2 = la = QLabel(_('Choose a &location (anchor) in the file:')) la.setBuddy(fn) fnl.addWidget(la), fnl.addWidget(f), fnl.addWidget(fn) h.addLayout(fnl), h.setStretch(1, 1) self.bb.addButton(self.bb.Help) self.bb.helpRequested.connect(self.help_requested) l.addWidget(self.bb) self.semantic_type_changed() self.semantic_type.currentIndexChanged.connect(self.semantic_type_changed) self.target.textChanged.connect(self.target_text_changed) def help_requested(self): d = info_dialog(self, _('About semantics'), _( 'Semantics refer to additional information about specific locations in the book.' ' For example, you can specify that a particular location is the dedication or the preface' ' or the table of contents and so on.\n\nFirst choose the type of semantic information, then' ' choose a file and optionally a location within the file to point to.\n\nThe' ' semantic information will be written in the <guide> section of the opf file.')) d.resize(d.sizeHint()) d.exec_() def semantic_type_changed(self): item_type = unicode(self.semantic_type.itemData(self.semantic_type.currentIndex()) or '') name, frag = self.final_type_map.get(item_type, (None, None)) self.show_type(name, frag) def show_type(self, name, frag): self.file_names_filter.clear(), self.anchor_names_filter.clear() self.file_names.clearSelection(), self.anchor_names.clearSelection() if name is not None: row = self.file_names.model().find_name(name) if row is not None: sm = self.file_names.selectionModel() sm.select(self.file_names.model().index(row), sm.ClearAndSelect) if frag: row = self.anchor_names.model().find_name(frag) if row is not None: sm = self.anchor_names.selectionModel() sm.select(self.anchor_names.model().index(row), sm.ClearAndSelect) self.target.blockSignals(True) if name is not None: self.target.setText(name + (('#' + frag) if frag else '')) else: self.target.setText('') self.target.blockSignals(False) def target_text_changed(self): name, frag = unicode(self.target.text()).partition('#')[::2] item_type = unicode(self.semantic_type.itemData(self.semantic_type.currentIndex()) or '') self.final_type_map[item_type] = (name, frag or None) def selected_file_changed(self, *args): rows = list(self.file_names.selectionModel().selectedRows()) if not rows: self.anchor_names.model().set_names([]) else: name, positions = self.file_names.model().data(rows[0], Qt.UserRole) self.populate_anchors(name) def populate_anchors(self, name): if name not in self.anchor_cache: from calibre.ebooks.oeb.base import XHTML_NS root = self.container.parsed(name) self.anchor_cache[name] = sorted( (set(root.xpath('//*/@id')) | set(root.xpath('//h:a/@name', namespaces={'h':XHTML_NS}))) - {''}, key=primary_sort_key) self.anchor_names.model().set_names(self.anchor_cache[name]) self.update_target() def update_target(self): rows = list(self.file_names.selectionModel().selectedRows()) if not rows: return name = self.file_names.model().data(rows[0], Qt.UserRole)[0] href = name frag = '' rows = list(self.anchor_names.selectionModel().selectedRows()) if rows: anchor = self.anchor_names.model().data(rows[0], Qt.UserRole)[0] if anchor: frag = '#' + anchor href += frag self.target.setText(href or '#') @property def changed_type_map(self): return {k:v for k, v in self.final_type_map.iteritems() if v != self.original_type_map.get(k, None)} def apply_changes(self, container): from calibre.ebooks.oeb.polish.opf import set_guide_item, get_book_language from calibre.translations.dynamic import translate lang = get_book_language(container) for item_type, (name, frag) in self.changed_type_map.iteritems(): title = self.known_type_map[item_type] if lang: title = translate(lang, title) set_guide_item(container, item_type, title, name, frag=frag) @classmethod def test(cls): import sys from calibre.ebooks.oeb.polish.container import get_container c = get_container(sys.argv[-1], tweak_mode=True) d = cls(c) if d.exec_() == d.Accepted: import pprint pprint.pprint(d.changed_type_map) d.apply_changes(d.container)
class MainWin(QMainWindow): def __init__(self, fileName=None, logName=None, parent=None): super(MainWin, self).__init__(parent) #self.setWindowIcon(QIcon(':/images/logo.png')) self.setToolButtonStyle(Qt.ToolButtonFollowStyle) self.setupFileActions() self.setupEditActions() self.setupTextActions() self.setupRunActions() self.initializeSettings() self.populateRunSettings() # FIXME put in initializeSettings()? settingsMenu = QMenu('Settings', self) self.menuBar().addMenu(settingsMenu) settingsMenu.addAction('Configure...', self.configure) helpMenu = QMenu("Help", self) self.menuBar().addMenu(helpMenu) helpMenu.addAction("About", self.about) helpMenu.addAction("About &Qt", QApplication.instance().aboutQt) self.splitter = QSplitter(self) self.splitter.setOrientation(Qt.Vertical) self.textPane = TextPane() self.logPane = LogPane() self.logBox = QGroupBox() self.logBox.setFlat(True) vbox = QVBoxLayout() vbox.addWidget(self.logPane) self.logBox.setLayout(vbox) self.splitter.addWidget(self.textPane) self.splitter.addWidget(QLabel()) # spacer self.splitter.addWidget(self.logBox) self.setCentralWidget(self.splitter) self.loadSrc(fileName) self.loadLog(logName) #if logName and (-1 == self.comboLogFile.findText(logName)): #self.comboLogFile.addItem(logName) self.logPane.setFocus() self.fontChanged(self.textPane.font()) self.textPane.document().modificationChanged.connect(self.actionSave.setEnabled) self.textPane.document().modificationChanged.connect(self.setWindowModified) self.textPane.document().undoAvailable.connect(self.actionUndo.setEnabled) self.textPane.document().redoAvailable.connect( self.actionRedo.setEnabled) self.setWindowModified(self.textPane.document().isModified()) self.actionSave.setEnabled(self.textPane.document().isModified()) self.actionUndo.setEnabled(self.textPane.document().isUndoAvailable()) self.actionRedo.setEnabled(self.textPane.document().isRedoAvailable()) self.actionUndo.triggered.connect(self.textPane.undo) self.actionRedo.triggered.connect(self.textPane.redo) self.actionCut.setEnabled(False) self.actionCopy.setEnabled(False) self.actionCut.triggered.connect(self.textPane.cut) self.actionCopy.triggered.connect(self.textPane.copy) self.actionPaste.triggered.connect(self.textPane.paste) self.textPane.copyAvailable.connect(self.actionCut.setEnabled) self.textPane.copyAvailable.connect(self.actionCopy.setEnabled) QApplication.clipboard().dataChanged.connect(self.clipboardDataChanged) self.actionRun.triggered.connect(self.scannoCheck) self.logPane.lineMatchChanged.connect(self.logLineMatchChanged) def closeEvent(self, e): if self.maybeSave(): e.accept() else: e.ignore() def setupFileActions(self): tb = QToolBar(self) tb.setWindowTitle("File Actions") self.addToolBar(tb) menu = QMenu("&File", self) self.menuBar().addMenu(menu) self.actionNew = QAction("&New", self, priority=QAction.LowPriority, shortcut=QKeySequence.New, triggered=self.fileNew) tb.addAction(self.actionNew) menu.addAction(self.actionNew) self.actionOpen = QAction("&Open...", self, shortcut=QKeySequence.Open, triggered=self.fileOpen) tb.addAction(self.actionOpen) menu.addAction(self.actionOpen) menu.addSeparator() self.actionSave = QAction("&Save", self, shortcut=QKeySequence.Save, triggered=self.fileSave, enabled=False) tb.addAction(self.actionSave) menu.addAction(self.actionSave) self.actionSaveAs = QAction("Save &As...", self, priority=QAction.LowPriority, shortcut=Qt.CTRL + Qt.SHIFT + Qt.Key_S, triggered=self.fileSaveAs) menu.addAction(self.actionSaveAs) menu.addSeparator() self.actionQuit = QAction("&Quit", self, shortcut=QKeySequence.Quit, triggered=self.close) menu.addAction(self.actionQuit) def setupEditActions(self): tb = QToolBar(self) tb.setWindowTitle("Edit Actions") self.addToolBar(tb) menu = QMenu("&Edit", self) self.menuBar().addMenu(menu) self.actionUndo = QAction("&Undo", self, shortcut=QKeySequence.Undo) tb.addAction(self.actionUndo) menu.addAction(self.actionUndo) self.actionRedo = QAction("&Redo", self, priority=QAction.LowPriority, shortcut=QKeySequence.Redo) tb.addAction(self.actionRedo) menu.addAction(self.actionRedo) menu.addSeparator() self.actionCut = QAction("Cu&t", self, priority=QAction.LowPriority, shortcut=QKeySequence.Cut) tb.addAction(self.actionCut) menu.addAction(self.actionCut) self.actionCopy = QAction("&Copy", self, priority=QAction.LowPriority, shortcut=QKeySequence.Copy) tb.addAction(self.actionCopy) menu.addAction(self.actionCopy) self.actionPaste = QAction("&Paste", self, priority=QAction.LowPriority, shortcut=QKeySequence.Paste, enabled=(len(QApplication.clipboard().text()) != 0)) tb.addAction(self.actionPaste) menu.addAction(self.actionPaste) def setupTextActions(self): tb = QToolBar(self) tb.setWindowTitle("Format Actions") self.addToolBar(tb) tb = QToolBar(self) tb.setAllowedAreas(Qt.TopToolBarArea | Qt.BottomToolBarArea) tb.setWindowTitle("Format Actions") self.addToolBarBreak(Qt.TopToolBarArea) self.addToolBar(tb) self.comboFont = QFontComboBox(tb) tb.addWidget(self.comboFont) self.comboFont.activated[str].connect(self.textFamily) self.comboSize = QComboBox(tb) self.comboSize.setObjectName("comboSize") tb.addWidget(self.comboSize) self.comboSize.setEditable(True) db = QFontDatabase() for size in db.standardSizes(): self.comboSize.addItem('{}'.format(size)) self.comboSize.activated[str].connect(self.textSize) self.comboSize.setCurrentIndex(self.comboSize.findText('{}'.format(QApplication.font().pointSize()))) def setupRunActions(self): tb = QToolBar(self) tb.setWindowTitle("Run Actions") self.addToolBar(tb) menu = QMenu("Run", self) self.menuBar().addMenu(menu) self.actionRun = QAction( "&Run", self, shortcut=Qt.CTRL + Qt.Key_R) tb.addAction(self.actionRun) menu.addAction(self.actionRun) self.comboScannoFile = QComboBox(tb) self.comboScannoFile.setObjectName("comboScannoFile") tb.addWidget(self.comboScannoFile) self.comboScannoFile.setEditable(True) self.comboLogFile= QComboBox(tb) self.comboLogFile.setObjectName("comboLogFile") self.comboLogFile.setEditable(True) tb.addWidget(self.comboLogFile) def populateRunSettings(self): for f in self.scannoFiles(): self.comboScannoFile.addItem(f) if self.defaultScannoFile: idx = self.comboScannoFile.findText(self.defaultScannoFile) self.comboScannoFile.setCurrentIndex(idx) self.comboLogFile.addItem('plog.txt') def loadSrc(self, src): if src: if not self.textPane.load(src): return False self.setCurrentFileName(src) return True def loadLog(self, log): if log: if not self.logPane.load(log): return False self.comboLogFile.clear() self.comboLogFile.addItem(log) else: self.logPane.clear() self.logPane.setEnabled(False) self.logBox.setTitle(self.tr('No log file loaded.')) return True def maybeSave(self): if not self.textPane.document().isModified(): return True ret = QMessageBox.warning(self, 'GuiScannos', 'The document has been modified.\n' 'Do you want to save your changes?', QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.fileSave() if ret == QMessageBox.Cancel: return False return True def setCurrentFileName(self, fileName=''): self.fileName = fileName self.textPane.document().setModified(False) if not fileName: shownName = 'untitled.txt' self.actionRun.setEnabled(False) else: shownName = QFileInfo(fileName).fileName() self.actionRun.setEnabled(True) self.setWindowTitle(self.tr('{}[*] - {}'.format(shownName, 'GUI Scannos'))) self.setWindowModified(False) def fileNew(self): if self.maybeSave(): self.textPane.clear() self.loadLog(None) # clears logPane, logBox title, etc self.setCurrentFileName() def fileOpen(self): fn, _ = QFileDialog.getOpenFileName(self, 'Open File...', None, 'Text Files (*.txt);;All Files (*)') if fn: self.loadSrc(fn) self.loadLog(None) # clears logPane, logBox title, etc def fileSave(self): if not self.fileName: return self.fileSaveAs() return self.textpane.save(self.fileName) def fileSaveAs(self): fn, _ = QFileDialog.getSaveFileName(self, "Save as...", None, "text files (*.txt);;All Files (*)") if not fn: return False self.setCurrentFileName(fn) return self.fileSave() def logLineMatchChanged(self): linenum = self.logPane.srcLineNum() col = self.logPane.srcColNum() s = self.logPane.srcScanno() self.textPane.setSelection(linenum, col, len(s)) def textFamily(self, family): """Set font family for text and log panes.""" self.textPane.setFontFamily(family) self.logPane.setFontFamily(family) def textSize(self, pointSize): """Set font size for text and log panes.""" self.textPane.setFontPointSize(pointSize) self.logPane.setFontPointSize(pointSize) def clipboardDataChanged(self): self.actionPaste.setEnabled(len(QApplication.clipboard().text()) != 0) def about(self): QMessageBox.about(self, 'About', 'GUI for ppscannos.') def fontChanged(self, font): self.comboFont.setCurrentIndex(self.comboFont.findText(QFontInfo(font).family())) self.comboSize.setCurrentIndex(self.comboSize.findText('{}'.format(font.pointSize()))) def scannoCheck(self): """Run ppscannos.""" scannodir = os.path.dirname(self.ppscannos) cmd = sys.executable assert(cmd) scannoFile = self.comboScannoFile.currentText() if not scannoFile: scannoFile = self.defaultScannoFile scannoFile = scannodir + '/' + scannoFile src = self.fileName log = self.comboLogFile.currentText() if not log: log = './plog.txt' subprocess.call([cmd, self.ppscannos, '-s' + scannoFile, '-o' + log, '-i' + src]) self.loadLog(log) self.logPane.setEnabled(True) def configure(self): """Configure application settings by way of a dialog.""" dlg = ConfigDialog() if dlg.exec(): self.setPPScannos(dlg.lineEditPPScannos.text()) self.setDefaultScannoFile(dlg.comboScannoFiles.currentText()) settings = QSettings(QApplication.organizationName(), QApplication.applicationName()) settings.setValue('ppscannos', self.ppscannos) settings.setValue('defaultScannoFile', self.defaultScannoFile) def setPPScannos(self, s): self.ppscannos = s self.actionRun.setEnabled(self.ppscannos and os.path.exists(self.ppscannos)) def scannoFiles(self): """Return list of .rc filenames (without path) that are in ppscannos directory.""" if not self.ppscannos: return [] return getRCFilesForDir(os.path.dirname(self.ppscannos)) def setDefaultScannoFile(self, s): self.defaultScannoFile = s valid = False if self.defaultScannoFile and self.ppscannos and os.path.exists(self.ppscannos): if os.path.exists(os.path.dirname(self.ppscannos) + '/' + self.defaultScannoFile): valid = True self.actionRun.setEnabled(valid) def initializeSettings(self): """Load persistent config settings.""" settings = QSettings() s = settings.value('ppscannos', type=str) if not s: # try the default s = os.path.expanduser('~') + '/ppscannos1/ppscannos1.py' #s = os.environ['HOME'] + '/ppscannos1/ppscannos1.py' self.setPPScannos(s) s = settings.value('defaultScannoFile', type=str) if (not s) and self.ppscannos: # try the default lst = getRCFilesForDir(os.path.dirname(self.ppscannos)) if len(lst): # prefer 'regex.rc'; otherwise use the first one s = lst[0] for f in lst: if f == 'regex.rc': s = f break self.setDefaultScannoFile(s)