class HashGeneratorTab(QWidget): def __init__(self, console): super().__init__() self.layout = QVBoxLayout(self) self.titleText = QLabel("<H1>HashGenerator</H1>\nText Einfügen") self.layout.addWidget(self.titleText) self.textField = QTextEdit() self.layout.addWidget(self.textField) self.selectHash = QComboBox() self.selectHash.addItems( ["SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "MD5"]) self.selectHash.setCurrentText("SHA512") self.layout.addWidget(self.selectHash) self.genButton = QPushButton("Generiere Hash") self.hashGenerator = HashGenerator() self.genButton.clicked.connect(self.generateHash) self.layout.addWidget(self.genButton) self.output = QTextEdit("Output") self.output.setReadOnly(True) self.layout.addWidget(self.output) self.layout.addStretch(1) def generateHash(self): text = self.textField.toPlainText() hash = self.selectHash.currentText() self.output.setText(self.hashGenerator.getHash(text, hash))
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()
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 HashcrackerTab(QWidget): def __init__(self, console): super().__init__() self.layout = QVBoxLayout(self) self.titleText = QLabel("<H1>Hashcracker</H1>\nHash hier einfügen") self.layout.addWidget(self.titleText) self.hashField = QLineEdit() self.layout.addWidget(self.hashField) self.hashSelectionLabel = QLabel("Wähle Hashfunktion aus") self.layout.addWidget(self.hashSelectionLabel) self.selectHash = QComboBox(self) self.selectHash.addItems(["SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "MD5"]) self.selectHash.setCurrentText("SHA-512") self.layout.addWidget(self.selectHash) self.hboxText = QHBoxLayout() self.bruteforceLabel = QLabel("<H2>Bruteforce</H2>") self.listLabel = QLabel("<H2>Passwort Liste</H2>") self.rtLabel = QLabel("<H2>Ranbowtable Crack</H2>") self.hboxText.addWidget(self.bruteforceLabel) self.hboxText.addWidget(self.listLabel) self.hboxText.addWidget(self.rtLabel) self.layout.addLayout(self.hboxText) self.hboxAction = QHBoxLayout() self.bruteforceCharset = QLineEdit("Charset") self.hboxAction.addWidget(self.bruteforceCharset) self.listSelect = QPushButton("Wähle Datei aus") self.hboxAction.addWidget(self.listSelect) self.rtSelect = QPushButton("Wähle Ranbowtable aus") self.hboxAction.addWidget(self.rtSelect) self.layout.addLayout(self.hboxAction) self.hboxCrackButton = QHBoxLayout() self.bruteforceCrack = QPushButton("Crack Bruteforce") self.hboxCrackButton.addWidget(self.bruteforceCrack) self.listCrack = QPushButton("Crack List") self.hboxCrackButton.addWidget(self.listCrack) self.rainbowCrack = QPushButton("Crack Rainbowtable") self.hboxCrackButton.addWidget(self.rainbowCrack) self.layout.addLayout(self.hboxCrackButton) self.layout.addStretch(1)
class OpdsDialog(QDialog): def __init__(self, gui, icon, do_user_config): QDialog.__init__(self, gui) self.gui = gui self.do_user_config = do_user_config self.db = gui.current_db.new_api # The model for the book list self.model = OpdsBooksModel(None, self.dummy_books(), self.db) self.searchproxymodel = QSortFilterProxyModel(self) self.searchproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.searchproxymodel.setFilterKeyColumn(-1) self.searchproxymodel.setSourceModel(self.model) self.layout = QGridLayout() self.setLayout(self.layout) self.setWindowTitle("OPDS Client") self.setWindowIcon(icon) labelColumnWidths = [] self.opdsUrlLabel = QLabel("OPDS URL: ") self.layout.addWidget(self.opdsUrlLabel, 0, 0) labelColumnWidths.append(self.layout.itemAtPosition(0, 0).sizeHint().width()) config.convertSingleStringOpdsUrlPreferenceToListOfStringsPreference() self.opdsUrlEditor = QComboBox(self) self.opdsUrlEditor.activated.connect(self.opdsUrlEditorActivated) self.opdsUrlEditor.addItems(prefs["opds_url"]) self.opdsUrlEditor.setEditable(True) self.opdsUrlEditor.setInsertPolicy(QComboBox.InsertAtTop) self.layout.addWidget(self.opdsUrlEditor, 0, 1, 1, 3) self.opdsUrlLabel.setBuddy(self.opdsUrlEditor) buttonColumnNumber = 7 buttonColumnWidths = [] self.about_button = QPushButton("About", self) self.about_button.setAutoDefault(False) self.about_button.clicked.connect(self.about) self.layout.addWidget(self.about_button, 0, buttonColumnNumber) buttonColumnWidths.append( self.layout.itemAtPosition(0, buttonColumnNumber).sizeHint().width() ) # Initially download the catalogs found in the root catalog of the URL # selected at startup. Fail quietly on failing to open the URL catalogsTuple = self.model.downloadOpdsRootCatalog( self.gui, self.opdsUrlEditor.currentText(), False ) print(catalogsTuple) firstCatalogTitle = catalogsTuple[0] self.currentOpdsCatalogs = catalogsTuple[1] # A dictionary of title->feedURL self.opdsCatalogSelectorLabel = QLabel("OPDS Catalog:") self.layout.addWidget(self.opdsCatalogSelectorLabel, 1, 0) labelColumnWidths.append(self.layout.itemAtPosition(1, 0).sizeHint().width()) self.opdsCatalogSelector = QComboBox(self) self.opdsCatalogSelector.setEditable(False) self.opdsCatalogSelectorModel = QStringListModel(self.currentOpdsCatalogs.keys()) self.opdsCatalogSelector.setModel(self.opdsCatalogSelectorModel) self.opdsCatalogSelector.setCurrentText(firstCatalogTitle) self.layout.addWidget(self.opdsCatalogSelector, 1, 1, 1, 3) self.download_opds_button = QPushButton("Download OPDS", self) self.download_opds_button.setAutoDefault(False) self.download_opds_button.clicked.connect(self.download_opds) self.layout.addWidget(self.download_opds_button, 1, buttonColumnNumber) buttonColumnWidths.append( self.layout.itemAtPosition(1, buttonColumnNumber).sizeHint().width() ) # Search GUI self.searchEditor = QLineEdit(self) self.searchEditor.returnPressed.connect(self.searchBookList) self.layout.addWidget(self.searchEditor, 2, buttonColumnNumber - 2, 1, 2) self.searchButton = QPushButton("Search", self) self.searchButton.setAutoDefault(False) self.searchButton.clicked.connect(self.searchBookList) self.layout.addWidget(self.searchButton, 2, buttonColumnNumber) buttonColumnWidths.append( self.layout.itemAtPosition(2, buttonColumnNumber).sizeHint().width() ) # The main book list self.library_view = QTableView(self) self.library_view.setAlternatingRowColors(True) self.library_view.setModel(self.searchproxymodel) self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch) self.library_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.resizeAllLibraryViewLinesToHeaderHeight() self.library_view.resizeColumnsToContents() self.layout.addWidget(self.library_view, 3, 0, 3, buttonColumnNumber + 1) self.hideNewsCheckbox = QCheckBox("Hide Newspapers", self) self.hideNewsCheckbox.clicked.connect(self.setHideNewspapers) self.hideNewsCheckbox.setChecked(prefs["hideNewspapers"]) self.layout.addWidget(self.hideNewsCheckbox, 6, 0, 1, 3) self.hideBooksAlreadyInLibraryCheckbox = QCheckBox("Hide books already in library", self) self.hideBooksAlreadyInLibraryCheckbox.clicked.connect(self.setHideBooksAlreadyInLibrary) self.hideBooksAlreadyInLibraryCheckbox.setChecked(prefs["hideBooksAlreadyInLibrary"]) self.layout.addWidget(self.hideBooksAlreadyInLibraryCheckbox, 7, 0, 1, 3) # Let the checkbox initial state control the filtering self.model.setFilterBooksThatAreNewspapers(self.hideNewsCheckbox.isChecked()) self.model.setFilterBooksThatAreAlreadyInLibrary( self.hideBooksAlreadyInLibraryCheckbox.isChecked() ) self.downloadButton = QPushButton("Download selected books", self) self.downloadButton.setAutoDefault(False) self.downloadButton.clicked.connect(self.downloadSelectedBooks) self.layout.addWidget(self.downloadButton, 6, buttonColumnNumber) buttonColumnWidths.append( self.layout.itemAtPosition(6, buttonColumnNumber).sizeHint().width() ) self.fixTimestampButton = QPushButton("Fix timestamps of selection", self) self.fixTimestampButton.setAutoDefault(False) self.fixTimestampButton.clicked.connect(self.fixBookTimestamps) self.layout.addWidget(self.fixTimestampButton, 7, buttonColumnNumber) buttonColumnWidths.append( self.layout.itemAtPosition(7, buttonColumnNumber).sizeHint().width() ) # Make all columns of the grid layout the same width as the button column buttonColumnWidth = max(buttonColumnWidths) for columnNumber in range(0, buttonColumnNumber): self.layout.setColumnMinimumWidth(columnNumber, buttonColumnWidth) # Make sure the first column isn't wider than the labels it holds labelColumnWidth = max(labelColumnWidths) self.layout.setColumnMinimumWidth(0, labelColumnWidth) self.resize(self.sizeHint()) def opdsUrlEditorActivated(self, text): prefs["opds_url"] = config.saveOpdsUrlCombobox(self.opdsUrlEditor) catalogsTuple = self.model.downloadOpdsRootCatalog( self.gui, self.opdsUrlEditor.currentText(), True ) firstCatalogTitle = catalogsTuple[0] self.currentOpdsCatalogs = catalogsTuple[1] # A dictionary of title->feedURL self.opdsCatalogSelectorModel.setStringList(self.currentOpdsCatalogs.keys()) self.opdsCatalogSelector.setCurrentText(firstCatalogTitle) def setHideNewspapers(self, checked): prefs["hideNewspapers"] = checked self.model.setFilterBooksThatAreNewspapers(checked) self.resizeAllLibraryViewLinesToHeaderHeight() def setHideBooksAlreadyInLibrary(self, checked): prefs["hideBooksAlreadyInLibrary"] = checked self.model.setFilterBooksThatAreAlreadyInLibrary(checked) self.resizeAllLibraryViewLinesToHeaderHeight() def searchBookList(self): searchString = self.searchEditor.text() print("starting book list search for: %s" % searchString) self.searchproxymodel.setFilterFixedString(searchString) def about(self): text = get_resources("about.txt") QMessageBox.about(self, "About the OPDS Client plugin", text.decode("utf-8")) def download_opds(self): opdsCatalogUrl = self.currentOpdsCatalogs.get(self.opdsCatalogSelector.currentText(), None) if opdsCatalogUrl is None: # Just give up quietly return self.model.downloadOpdsCatalog(self.gui, opdsCatalogUrl) if self.model.isCalibreOpdsServer(): self.model.downloadMetadataUsingCalibreRestApi(self.opdsUrlEditor.currentText()) self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch) self.resizeAllLibraryViewLinesToHeaderHeight() self.resize(self.sizeHint()) def config(self): self.do_user_config(parent=self) def downloadSelectedBooks(self): selectionmodel = self.library_view.selectionModel() if selectionmodel.hasSelection(): rows = selectionmodel.selectedRows() for row in reversed(rows): book = row.data(Qt.UserRole) self.downloadBook(book) def downloadBook(self, book): if len(book.links) > 0: self.gui.download_ebook(book.links[0]) def fixBookTimestamps(self): selectionmodel = self.library_view.selectionModel() if selectionmodel.hasSelection(): rows = selectionmodel.selectedRows() for row in reversed(rows): book = row.data(Qt.UserRole) self.fixBookTimestamp(book) def fixBookTimestamp(self, book): bookTimestamp = book.timestamp identicalBookIds = self.findIdenticalBooksForBooksWithMultipleAuthors(book) bookIdToValMap = {} for identicalBookId in identicalBookIds: bookIdToValMap[identicalBookId] = bookTimestamp if len(bookIdToValMap) < 1: print("Failed to set timestamp of book: %s" % book) self.db.set_field("timestamp", bookIdToValMap) def findIdenticalBooksForBooksWithMultipleAuthors(self, book): authorsList = book.authors if len(authorsList) < 2: return self.db.find_identical_books(book) # Try matching the authors one by one identicalBookIds = set() for author in authorsList: singleAuthorBook = Metadata(book.title, [author]) singleAuthorIdenticalBookIds = self.db.find_identical_books(singleAuthorBook) identicalBookIds = identicalBookIds.union(singleAuthorIdenticalBookIds) return identicalBookIds def dummy_books(self): dummy_author = " " * 40 dummy_title = " " * 60 books_list = [] for line in range(1, 10): book = DynamicBook() book.author = dummy_author book.title = dummy_title book.updated = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S+00:00") book.id = "" books_list.append(book) return books_list def resizeAllLibraryViewLinesToHeaderHeight(self): rowHeight = self.library_view.horizontalHeader().height() for rowNumber in range(0, self.library_view.model().rowCount()): self.library_view.setRowHeight(rowNumber, rowHeight)
def __init__(self, main, channels, default_channel=None): super(ChannelAddWidget, self).__init__() self.setObjectName("ChannelAddWidget") self.main_win = main self.channels = channels self.default_channel = default_channel self.channel = {} self.linedit_list = [] self.game = self.main_win.games[self.main_win.game_index] combox_items = os.listdir(Utils.get_full_path('channelsdk')) v_layout = QVBoxLayout() v_layout.addSpacing(30) select_channel_combox = QComboBox() select_channel_combox.addItems(combox_items) select_channel_combox.activated[str].connect(self.select_channel) v_layout.addWidget(select_channel_combox, alignment=Qt.AlignHCenter) v_layout.addSpacing(30) h_layout1 = QHBoxLayout() form_layout1 = QFormLayout() form_layout1.setContentsMargins(10, 10, 10, 0) game_appid_value = QLabel(self.game['id']) form_layout1.addRow("游戏ID:", game_appid_value) game_appid_value.setTextInteractionFlags(Qt.TextSelectableByMouse) self.channel_id_value = QLineEdit() self.channel_id_value.setPlaceholderText("必填参数") form_layout1.addRow("渠道ID:", self.channel_id_value) self.game_name_value = QLineEdit() self.game_name_value.setText(self.game['name']) form_layout1.addRow("游戏名称:", self.game_name_value) self.game_package_value = QLineEdit() form_layout1.addRow("游戏包名:", self.game_package_value) self.game_vcode_value = QLineEdit() form_layout1.addRow("游戏版本号:", self.game_vcode_value) self.game_vname_value = QLineEdit() form_layout1.addRow("游戏版本名:", self.game_vname_value) self.debug_value = QLineEdit("false") form_layout1.addRow("打印日志:", self.debug_value) h_layout1.addLayout(form_layout1) self.form_layout2 = QFormLayout() self.form_layout2.setContentsMargins(10, 10, 10, 0) h_layout1.addLayout(self.form_layout2) v_layout.addLayout(h_layout1) h_layout2 = QHBoxLayout() back_btn = QPushButton("返 回") back_btn.setFixedWidth(100) back_btn.clicked.connect(self.back) h_layout2.addWidget(back_btn, alignment=Qt.AlignLeft) add_btn = QPushButton("添 加") add_btn.setFixedWidth(100) add_btn.clicked.connect(self.add) h_layout2.addWidget(add_btn, alignment=Qt.AlignRight) v_layout.addSpacing(50) v_layout.addLayout(h_layout2) self.setLayout(v_layout) # 默认松鼠SDK select_channel_combox.setCurrentText("songshu") self.select_channel("songshu")
class MainWindow(QWidget): def __init__(self, appinst, profilecon, settingscon, *args, **kwargs): super().__init__(*args, **kwargs) self.app = appinst self.profilecon = profilecon # connector class instance for reading/writing profile settings self.settingscon = settingscon self.gcode = None self.machine = None self.backgroundTask = None self.postBackgroundTask = None self.coord_plot_items = list( ) # list of all plot items added to the coord plot self.mainlayout = QVBoxLayout(self) self.mainlayout.setContentsMargins(0, 0, 0, 0) self.toolBar = QToolBar() self.toolBar.setStyleSheet("""QToolBar {background-color: white; border-top: 1px solid black}""" ) self.mainlayout.addWidget(self.toolBar) self.add_toolbar_action("./res/folder.svg", "Open", self.open_file_dialog) self.add_toolbar_action("./res/x-square.svg", "Close", self.close_file) self.add_toolbar_action("./res/save.svg", "Export", self.export) self.toolBar.addSeparator() self.add_toolbar_action("./res/sliders.svg", "Settings", self.open_settings_dialog) self.add_toolbar_action("./res/play.svg", "Simulate", self.start_simulation) self.toolBar.addSeparator() self.add_toolbar_action("./res/maximize.svg", "Fit to View", self.fit_plot_to_window) self.add_toolbar_action("./res/maximize-2.svg", "Reset View", self.reset_plot_view) self.toolBar.addSeparator() self.profileSelector = QComboBox() for name in self.profilecon.list_profiles(): self.profileSelector.addItem(name) self.profileSelector.setCurrentText( self.settingscon.get_value("Current_Profile")) self.profilecon.select_profile( self.settingscon.get_value("Current_Profile")) self.toolBar.addWidget(self.profileSelector) self.profileSelector.currentTextChanged.connect( self.selected_profile_changed) divider = QWidget() divider.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolBar.addWidget(divider) self.add_toolbar_action("./res/info.svg", "About", self.open_about_dialog) self.contentLayout = QHBoxLayout() self.contentLayout.setContentsMargins(10, 10, 10, 10) self.mainlayout.addLayout(self.contentLayout) self.layerSlider = QSlider() self.layerSlider.setMinimum(0) self.layerSlider.setValue(0) self.layerSlider.setDisabled(True) self.layerSlider.valueChanged.connect(self.show_layer) self.contentLayout.addWidget(self.layerSlider) self.coordPlot = PlotWidget() self.coordPlot.setAspectLocked(True) # self.coordPlot.setLimits(xMin=0, yMin=0) self.configure_plot( ) # is done in a seperate funciton because values need to be updated after settings are changed self.contentLayout.addWidget(self.coordPlot) self.sidebarlayout = QVBoxLayout() self.contentLayout.addLayout(self.sidebarlayout) self.sidebarheader = QLabel("Options") self.sidebarheader.setFixedSize(300, 50) self.sidebarlayout.addWidget(self.sidebarheader) def configure_plot(self): self.coordPlot.invertX( self.profilecon.get_value("invert_x") ) # needs to be done before setting the axis ranges because self.coordPlot.invertY( self.profilecon.get_value("invert_y") ) # inverting does not update the viewbox, but setting the range does self.coordPlot.setXRange(self.profilecon.get_value("bed_min_x"), self.profilecon.get_value("bed_max_x")) self.coordPlot.setYRange(self.profilecon.get_value("bed_min_y"), self.profilecon.get_value("bed_max_y")) def selected_profile_changed(self, new_profile): # select the new profile in the settings connector and update the ui accordingly self.profilecon.select_profile(new_profile) self.settingscon.set_value("Current_Profile", new_profile) # remember selected profile self.settingscon.save_to_file() self.configure_plot() def add_toolbar_action(self, icon, text, function): # wrapper function for adding a toolbar button and connecting it to trigger a function open_icon = QIcon(icon) action = self.toolBar.addAction(open_icon, text) action.triggered.connect(function) def finish_background_task(self): # function is called when a background task finishes if self.postBackgroundTask: # run cleanup task (i.e. ui update); runs on main ui thread! self.postBackgroundTask() # reset variables self.postBackgroundTask = None self.backgroundTask = None def run_in_background(self, task, after=None, args=None): # wrapper function for creating and starting a thread to run a function in the background # arguments can be passed to the function in the thread and a cleanup function can be specified # which is run on the main ui thread when the background task is finished self.backgroundTask = BackgroundTask(task) if args: self.backgroundTask.set_arguments(args) self.backgroundTask.finished.connect(self.finish_background_task) self.postBackgroundTask = after self.backgroundTask.start() def open_file_dialog(self): # in case a file is open already, close it properly first if self.machine: ret = self.close_file() if not ret: # user canceled closing of current file; can't open new one return # open dialog for selecting a gcode file to be loaded dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.ExistingFile) filters = ["G-code (*.gcode)", "Any files (*)"] dialog.setNameFilters(filters) dialog.selectNameFilter(filters[0]) dialog.setViewMode(QFileDialog.Detail) filename = None if dialog.exec_(): filename = dialog.selectedFiles() if filename: self.run_in_background(self.load_data, after=self.show_layer, args=filename) def open_settings_dialog(self): # open a dialog with settings dialog = SettingsDialog(self, self.profilecon) dialog.exec() # update settings self.configure_plot() def open_about_dialog(self): # open the about dialog dialog = QDialog() dialog.setWindowTitle("About...") layout = QVBoxLayout() dialog.setLayout(layout) text = QLabel(strings.about) layout.addWidget(text) dialog.exec() def close_file(self): # close the current gcode file, discard all data # Before, ask for user confirmation cfmsgbox = QMessageBox() cfmsgbox.setWindowTitle("Close file?") cfmsgbox.setText( "Are you sure you want to close the current file and discard all unsaved data?" ) cfmsgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) cfmsgbox.setDefaultButton(QMessageBox.No) ret = cfmsgbox.exec() if ret == QMessageBox.Yes: for item in self.coord_plot_items: self.coordPlot.removeItem(item) self.machine = None self.gcode = None # TODO: fix: this will not terminate a running background process return True return False def export(self): pass def start_simulation(self): pass def fit_plot_to_window(self): x, y = self.machine.get_path_coordinates( layer_number=self.layerSlider.value()) self.coordPlot.setRange(xRange=(min(x), max(x)), yRange=(min(y), max(y))) def reset_plot_view(self): self.coordPlot.setXRange(self.profilecon.get_value("bed_min_x"), self.profilecon.get_value("bed_max_x")) self.coordPlot.setYRange(self.profilecon.get_value("bed_min_y"), self.profilecon.get_value("bed_max_y")) def load_data(self, filename): # initalizes a virtual machine from the gcode in the file given # all path data for this gcode is calculated; this is a cpu intensive task! self.gcode = GCode() self.gcode.load_file(filename) self.machine = Machine(self.gcode, self.profilecon) self.machine.create_path() # set the layer sliders maximum to represent the given amount of layers and enable the slider self.layerSlider.setMaximum(len(self.machine.layers) - 1) self.layerSlider.setEnabled(True) def show_layer(self): # plot path for the layer selected by the layer slider x, y = self.machine.get_path_coordinates( layer_number=self.layerSlider.value()) pltitm = self.coordPlot.plot(x, y, clear=True) self.coord_plot_items.append(pltitm)
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QVBoxLayout() self.l.setContentsMargins(0, 0, 0, 0) self.setLayout(self.l) self.help_msg = QLabel(''' <h2 style="text-align: center">Get Started</h2> <p> To start syncing your library you will need to create an account to retrieve<br> your API key. </p> ''') self.l.addWidget(self.help_msg) self.form = QFormLayout() self.form.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.l.addLayout(self.form) self.link = QLabel('<a href="{0}">{0}</a>'.format(prefs['api_base'] + '/api-key')) self.link.setOpenExternalLinks(True) self.form.addRow('Visit:', self.link) self.api_key = QLineEdit(self) self.api_key.setText(prefs['api_key']) self.form.addRow('API Key:', self.api_key) self.debug = QCheckBox(self) self.debug.setChecked(prefs['debug']) self.form.addRow('Debug Logging:', self.debug) self.update_metadata_layout = QHBoxLayout() self.update_metadata_layout.setContentsMargins(0, 0, 0, 0) self.update_metadata = QCheckBox(self) self.update_metadata.setChecked(prefs['update_metadata']) self.update_metadata_layout.addWidget(self.update_metadata) self.update_metadata_hint = QLabel('(sync all metadata changes made)') self.update_metadata_layout.addWidget(self.update_metadata_hint) self.form.addRow('Update Metadata:', self.update_metadata_layout) self.threads = QComboBox(self) for n in range(3): self.threads.addItem(str(pow(2, n))) self.threads.setCurrentText(str(prefs['threads'])) self.form.addRow('Sync Threads:', self.threads) self.bookshelves_custom_column = QComboBox(self) self.bookshelves_custom_column.addItem('') for key, meta in get_current_db().new_api.field_metadata.custom_iteritems(): if meta['datatype'] == 'text': self.bookshelves_custom_column.addItem(key) self.bookshelves_custom_column.setCurrentText(prefs['bookshelves_custom_column']) self.form.addRow('Bookshelves Column:', self.bookshelves_custom_column) def save_settings(self): prefs['api_key'] = unicode(self.api_key.text()) prefs['debug'] = self.debug.isChecked() prefs['update_metadata'] = self.update_metadata.isChecked() prefs['threads'] = int(self.threads.currentText()) prefs['bookshelves_custom_column'] = unicode(self.bookshelves_custom_column.currentText())
class OpdsDialog(QDialog): def __init__(self, gui, icon, do_user_config): QDialog.__init__(self, gui) self.gui = gui self.do_user_config = do_user_config self.db = gui.current_db.new_api # The model for the book list self.model = OpdsBooksModel(None, self.dummy_books(), self.db) self.searchproxymodel = QSortFilterProxyModel(self) self.searchproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.searchproxymodel.setFilterKeyColumn(-1) self.searchproxymodel.setSourceModel(self.model) self.layout = QGridLayout() self.setLayout(self.layout) self.setWindowTitle('OPDS Client') self.setWindowIcon(icon) labelColumnWidths = [] self.opdsUrlLabel = QLabel('OPDS URL: ') self.layout.addWidget(self.opdsUrlLabel, 0, 0) labelColumnWidths.append(self.layout.itemAtPosition(0, 0).sizeHint().width()) config.convertSingleStringOpdsUrlPreferenceToListOfStringsPreference() self.opdsUrlEditor = QComboBox(self) self.opdsUrlEditor.activated.connect(self.opdsUrlEditorActivated) self.opdsUrlEditor.addItems(prefs['opds_url']) self.opdsUrlEditor.setEditable(True) self.opdsUrlEditor.setInsertPolicy(QComboBox.InsertAtTop) self.layout.addWidget(self.opdsUrlEditor, 0, 1, 1, 3) self.opdsUrlLabel.setBuddy(self.opdsUrlEditor) buttonColumnNumber = 7 buttonColumnWidths = [] self.about_button = QPushButton('About', self) self.about_button.setAutoDefault(False) self.about_button.clicked.connect(self.about) self.layout.addWidget(self.about_button, 0, buttonColumnNumber) buttonColumnWidths.append(self.layout.itemAtPosition(0, buttonColumnNumber).sizeHint().width()) # Initially download the catalogs found in the root catalog of the URL # selected at startup. Fail quietly on failing to open the URL catalogsTuple = self.model.downloadOpdsRootCatalog(self.gui, self.opdsUrlEditor.currentText(), False) print catalogsTuple firstCatalogTitle = catalogsTuple[0] self.currentOpdsCatalogs = catalogsTuple[1] # A dictionary of title->feedURL self.opdsCatalogSelectorLabel = QLabel('OPDS Catalog:') self.layout.addWidget(self.opdsCatalogSelectorLabel, 1, 0) labelColumnWidths.append(self.layout.itemAtPosition(1, 0).sizeHint().width()) self.opdsCatalogSelector = QComboBox(self) self.opdsCatalogSelector.setEditable(False) self.opdsCatalogSelectorModel = QStringListModel(self.currentOpdsCatalogs.keys()) self.opdsCatalogSelector.setModel(self.opdsCatalogSelectorModel) self.opdsCatalogSelector.setCurrentText(firstCatalogTitle) self.layout.addWidget(self.opdsCatalogSelector, 1, 1, 1, 3) self.download_opds_button = QPushButton('Download OPDS', self) self.download_opds_button.setAutoDefault(False) self.download_opds_button.clicked.connect(self.download_opds) self.layout.addWidget(self.download_opds_button, 1, buttonColumnNumber) buttonColumnWidths.append(self.layout.itemAtPosition(1, buttonColumnNumber).sizeHint().width()) # Search GUI self.searchEditor = QLineEdit(self) self.searchEditor.returnPressed.connect(self.searchBookList) self.layout.addWidget(self.searchEditor, 2, buttonColumnNumber - 2, 1, 2) self.searchButton = QPushButton('Search', self) self.searchButton.setAutoDefault(False) self.searchButton.clicked.connect(self.searchBookList) self.layout.addWidget(self.searchButton, 2, buttonColumnNumber) buttonColumnWidths.append(self.layout.itemAtPosition(2, buttonColumnNumber).sizeHint().width()) # The main book list self.library_view = QTableView(self) self.library_view.setAlternatingRowColors(True) self.library_view.setModel(self.searchproxymodel) self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch) self.library_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.resizeAllLibraryViewLinesToHeaderHeight() self.library_view.resizeColumnsToContents() self.layout.addWidget(self.library_view, 3, 0, 3, buttonColumnNumber + 1) self.hideNewsCheckbox = QCheckBox('Hide Newspapers', self) self.hideNewsCheckbox.clicked.connect(self.setHideNewspapers) self.hideNewsCheckbox.setChecked(prefs['hideNewspapers']) self.layout.addWidget(self.hideNewsCheckbox, 6, 0, 1, 3) self.hideBooksAlreadyInLibraryCheckbox = QCheckBox('Hide books already in library', self) self.hideBooksAlreadyInLibraryCheckbox.clicked.connect(self.setHideBooksAlreadyInLibrary) self.hideBooksAlreadyInLibraryCheckbox.setChecked(prefs['hideBooksAlreadyInLibrary']) self.layout.addWidget(self.hideBooksAlreadyInLibraryCheckbox, 7, 0, 1, 3) # Let the checkbox initial state control the filtering self.model.setFilterBooksThatAreNewspapers(self.hideNewsCheckbox.isChecked()) self.model.setFilterBooksThatAreAlreadyInLibrary(self.hideBooksAlreadyInLibraryCheckbox.isChecked()) self.downloadButton = QPushButton('Download selected books', self) self.downloadButton.setAutoDefault(False) self.downloadButton.clicked.connect(self.downloadSelectedBooks) self.layout.addWidget(self.downloadButton, 6, buttonColumnNumber) buttonColumnWidths.append(self.layout.itemAtPosition(6, buttonColumnNumber).sizeHint().width()) self.fixTimestampButton = QPushButton('Fix timestamps of selection', self) self.fixTimestampButton.setAutoDefault(False) self.fixTimestampButton.clicked.connect(self.fixBookTimestamps) self.layout.addWidget(self.fixTimestampButton, 7, buttonColumnNumber) buttonColumnWidths.append(self.layout.itemAtPosition(7, buttonColumnNumber).sizeHint().width()) # Make all columns of the grid layout the same width as the button column buttonColumnWidth = max(buttonColumnWidths) for columnNumber in range(0, buttonColumnNumber): self.layout.setColumnMinimumWidth(columnNumber, buttonColumnWidth) # Make sure the first column isn't wider than the labels it holds labelColumnWidth = max(labelColumnWidths) self.layout.setColumnMinimumWidth(0, labelColumnWidth) self.resize(self.sizeHint()) def opdsUrlEditorActivated(self, text): prefs['opds_url'] = config.saveOpdsUrlCombobox(self.opdsUrlEditor) catalogsTuple = self.model.downloadOpdsRootCatalog(self.gui, self.opdsUrlEditor.currentText(), True) firstCatalogTitle = catalogsTuple[0] self.currentOpdsCatalogs = catalogsTuple[1] # A dictionary of title->feedURL self.opdsCatalogSelectorModel.setStringList(self.currentOpdsCatalogs.keys()) self.opdsCatalogSelector.setCurrentText(firstCatalogTitle) def setHideNewspapers(self, checked): prefs['hideNewspapers'] = checked self.model.setFilterBooksThatAreNewspapers(checked) self.resizeAllLibraryViewLinesToHeaderHeight() def setHideBooksAlreadyInLibrary(self, checked): prefs['hideBooksAlreadyInLibrary'] = checked self.model.setFilterBooksThatAreAlreadyInLibrary(checked) self.resizeAllLibraryViewLinesToHeaderHeight() def searchBookList(self): searchString = self.searchEditor.text() print "starting book list search for: %s" % searchString self.searchproxymodel.setFilterFixedString(searchString) def about(self): text = get_resources('about.txt') QMessageBox.about(self, 'About the OPDS Client plugin', text.decode('utf-8')) def download_opds(self): opdsCatalogUrl = self.currentOpdsCatalogs.get(self.opdsCatalogSelector.currentText(), None) if opdsCatalogUrl is None: # Just give up quietly return self.model.downloadOpdsCatalog(self.gui, opdsCatalogUrl) if self.model.isCalibreOpdsServer(): self.model.downloadMetadataUsingCalibreRestApi(self.opdsUrlEditor.currentText()) self.library_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) self.library_view.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch) self.resizeAllLibraryViewLinesToHeaderHeight() self.resize(self.sizeHint()) def config(self): self.do_user_config(parent=self) def downloadSelectedBooks(self): selectionmodel = self.library_view.selectionModel() if selectionmodel.hasSelection(): rows = selectionmodel.selectedRows() for row in reversed(rows): book = row.data(Qt.UserRole) self.downloadBook(book) def downloadBook(self, book): if len(book.links) > 0: self.gui.download_ebook(book.links[0]) def fixBookTimestamps(self): selectionmodel = self.library_view.selectionModel() if selectionmodel.hasSelection(): rows = selectionmodel.selectedRows() for row in reversed(rows): book = row.data(Qt.UserRole) self.fixBookTimestamp(book) def fixBookTimestamp(self, book): bookTimestamp = book.timestamp identicalBookIds = self.findIdenticalBooksForBooksWithMultipleAuthors(book) bookIdToValMap = {} for identicalBookId in identicalBookIds: bookIdToValMap[identicalBookId] = bookTimestamp if len(bookIdToValMap) < 1: print "Failed to set timestamp of book: %s" % book self.db.set_field('timestamp', bookIdToValMap) def findIdenticalBooksForBooksWithMultipleAuthors(self, book): authorsList = book.authors if len(authorsList) < 2: return self.db.find_identical_books(book) # Try matching the authors one by one identicalBookIds = set() for author in authorsList: singleAuthorBook = Metadata(book.title, [author]) singleAuthorIdenticalBookIds = self.db.find_identical_books(singleAuthorBook) identicalBookIds = identicalBookIds.union(singleAuthorIdenticalBookIds) return identicalBookIds def dummy_books(self): dummy_author = ' ' * 40 dummy_title = ' ' * 60 books_list = [] for line in range (1, 10): book = DynamicBook() book.author = dummy_author book.title = dummy_title book.updated = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S+00:00') book.id = '' books_list.append(book) return books_list def resizeAllLibraryViewLinesToHeaderHeight(self): rowHeight = self.library_view.horizontalHeader().height() for rowNumber in range (0, self.library_view.model().rowCount()): self.library_view.setRowHeight(rowNumber, rowHeight)