class DataTypeKeysWidget(QWidget): dataTypeKeySelected = Signal() def __init__(self, model): QWidget.__init__(self) self.__filter_popup = FilterPopup(self) self.__filter_popup.filterSettingsChanged.connect(self.onItemChanged) layout = QVBoxLayout() self.model = model self.filter_model = DataTypeProxyModel(self.model) filter_layout = QHBoxLayout() self.search_box = SearchBox() self.search_box.filterChanged.connect(self.setSearchString) filter_layout.addWidget(self.search_box) filter_popup_button = QToolButton() filter_popup_button.setIcon(resourceIcon("ide/cog_edit.png")) filter_popup_button.clicked.connect(self.showFilterPopup) filter_layout.addWidget(filter_popup_button) layout.addLayout(filter_layout) self.data_type_keys_widget = QListView() self.data_type_keys_widget.setModel(self.filter_model) self.data_type_keys_widget.selectionModel().selectionChanged.connect( self.itemSelected) layout.addSpacing(15) layout.addWidget(self.data_type_keys_widget, 2) layout.addStretch() # layout.addWidget(Legend("Default types", DataTypeKeysListModel.DEFAULT_DATA_TYPE)) layout.addWidget( Legend("Observations available", DataTypeKeysListModel.HAS_OBSERVATIONS)) self.setLayout(layout) def onItemChanged(self, item): # self.filter_model.setShowBlockKeys(item["block"]) self.filter_model.setShowSummaryKeys(item["summary"]) self.filter_model.setShowGenKWKeys(item["gen_kw"]) self.filter_model.setShowGenDataKeys(item["gen_data"]) self.filter_model.setShowCustomKwKeys(item["custom_kw"]) # self.filter_model.setShowCustomPcaKeys(item["custom_pca"]) def itemSelected(self): selected_item = self.getSelectedItem() if selected_item is not None: self.dataTypeKeySelected.emit() def getSelectedItem(self): """ @rtype: str """ index = self.data_type_keys_widget.currentIndex() source_index = self.filter_model.mapToSource(index) item = self.model.itemAt(source_index) return item def selectDefault(self): self.data_type_keys_widget.setCurrentIndex( self.filter_model.index(0, 0)) def setSearchString(self, filter): self.filter_model.setFilterFixedString(filter) def showFilterPopup(self): self.__filter_popup.show()
class Switcher(QDialog): """ A multi purpose switcher. Example ------- SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] SwitcherSeparator: [---------------------------------------] SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] """ # Dismissed switcher sig_rejected = Signal() # Search/Filter text changes sig_text_changed = Signal(TEXT_TYPES[-1]) # Current item changed sig_item_changed = Signal(object) # List item selected, mode and cleaned search text sig_item_selected = Signal(object, TEXT_TYPES[-1], TEXT_TYPES[-1], ) sig_mode_selected = Signal(TEXT_TYPES[-1]) _MAX_NUM_ITEMS = 15 _MIN_WIDTH = 580 _MIN_HEIGHT = 200 _MAX_HEIGHT = 390 _ITEM_WIDTH = _MIN_WIDTH - 20 def __init__(self, parent, help_text=None, item_styles=ITEM_STYLES, item_separator_styles=ITEM_SEPARATOR_STYLES): """Multi purpose switcher.""" super(Switcher, self).__init__(parent) self._modes = {} self._mode_on = '' self._item_styles = item_styles self._item_separator_styles = item_separator_styles # Widgets self.edit = QLineEdit(self) self.list = QListView(self) self.model = QStandardItemModel(self.list) self.proxy = SwitcherProxyModel(self.list) self.filter = KeyPressFilter() # Widgets setup self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint) self.setWindowOpacity(0.95) # self.setMinimumHeight(self._MIN_HEIGHT) self.setMaximumHeight(self._MAX_HEIGHT) self.edit.installEventFilter(self.filter) self.edit.setPlaceholderText(help_text if help_text else '') self.list.setMinimumWidth(self._MIN_WIDTH) self.list.setItemDelegate(SwitcherDelegate(self)) self.list.setFocusPolicy(Qt.NoFocus) self.list.setSelectionBehavior(self.list.SelectItems) self.list.setSelectionMode(self.list.SingleSelection) self.list.setVerticalScrollMode(QAbstractItemView.ScrollPerItem) self.proxy.setSourceModel(self.model) self.list.setModel(self.proxy) # Layout layout = QVBoxLayout() layout.addWidget(self.edit) layout.addWidget(self.list) self.setLayout(layout) # Signals self.filter.sig_up_key_pressed.connect(self.previous_row) self.filter.sig_down_key_pressed.connect(self.next_row) self.filter.sig_enter_key_pressed.connect(self.enter) self.edit.textChanged.connect(self.setup) self.edit.textChanged.connect(self.sig_text_changed) self.edit.returnPressed.connect(self.enter) self.list.clicked.connect(self.enter) self.list.clicked.connect(self.edit.setFocus) self.list.selectionModel().currentChanged.connect( self.current_item_changed) self.edit.setFocus() # --- Helper methods def _add_item(self, item, last_item=True): """Perform common actions when adding items.""" item.set_width(self._ITEM_WIDTH) self.model.appendRow(item) if last_item: # Only set the current row to the first item when the added item is # the last one in order to prevent performance issues when # adding multiple items self.set_current_row(0) self.set_height() self.setup_sections() # --- API def clear(self): """Remove all items from the list and clear the search text.""" self.set_placeholder_text('') self.model.beginResetModel() self.model.clear() self.model.endResetModel() self.setMinimumHeight(self._MIN_HEIGHT) def set_placeholder_text(self, text): """Set the text appearing on the empty line edit.""" self.edit.setPlaceholderText(text) def add_mode(self, token, description): """Add mode by token key and description.""" if len(token) == 1: self._modes[token] = description else: raise Exception('Token must be of length 1!') def get_mode(self): """Get the current mode the switcher is in.""" return self._mode_on def remove_mode(self, token): """Remove mode by token key.""" if token in self._modes: self._modes.pop(token) def clear_modes(self): """Delete all modes spreviously defined.""" del self._modes self._modes = {} def add_item(self, icon=None, title=None, description=None, shortcut=None, section=None, data=None, tool_tip=None, action_item=False, last_item=True): """Add switcher list item.""" item = SwitcherItem( parent=self.list, icon=icon, title=title, description=description, data=data, shortcut=shortcut, section=section, action_item=action_item, tool_tip=tool_tip, styles=self._item_styles ) self._add_item(item, last_item=last_item) def add_separator(self): """Add separator item.""" item = SwitcherSeparatorItem(parent=self.list, styles=self._item_separator_styles) self._add_item(item) def setup(self): """Set-up list widget content based on the filtering.""" # Check exited mode mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() # Check exited mode if self.search_text() == '': self._mode_on = '' self.clear() self.proxy.set_filter_by_score(False) self.sig_mode_selected.emit(self._mode_on) return # Check entered mode for key in self._modes: if self.search_text().startswith(key) and not mode: self._mode_on = key self.sig_mode_selected.emit(key) return # Filter by text titles = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): title = item.get_title() else: title = '' titles.append(title) search_text = clean_string(search_text) scores = get_search_scores(to_text_string(search_text), titles, template=u"<b>{0}</b>") for idx, (title, rich_title, score_value) in enumerate(scores): item = self.model.item(idx) if not self._is_separator(item) and not item.is_action_item(): rich_title = rich_title.replace(" ", " ") item.set_rich_title(rich_title) item.set_score(score_value) self.proxy.set_filter_by_score(True) self.setup_sections() if self.count(): self.set_current_row(0) else: self.set_current_row(-1) self.set_height() def setup_sections(self): """Set-up which sections appear on the item list.""" mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() if search_text: for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): item.set_section_visible(False) else: sections = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): sections.append(item.get_section()) item.set_section_visible(bool(search_text)) else: sections.append('') if row != 0: visible = sections[row] != sections[row - 1] if not self._is_separator(item): item.set_section_visible(visible) else: item.set_section_visible(True) self.proxy.sortBy('_score') self.sig_item_changed.emit(self.current_item()) def set_height(self): """Set height taking into account the number of items.""" if self.count() >= self._MAX_NUM_ITEMS: switcher_height = self._MAX_HEIGHT elif self.count() != 0 and self.current_item(): current_item = self.current_item() item_height = current_item.get_height() list_height = item_height * (self.count() + 3) edit_height = self.edit.height() spacing_height = self.layout().spacing() * 4 switcher_height = list_height + edit_height + spacing_height switcher_height = max(switcher_height, self._MIN_HEIGHT) else: switcher_height = self._MIN_HEIGHT self.setFixedHeight(int(switcher_height)) def set_position(self, top): """Set the position of the dialog.""" parent = self.parent() if parent is not None: geo = parent.geometry() width = self.list.width() # This has been set in setup left = parent.geometry().width()/2 - width/2 while parent: geo = parent.geometry() top += geo.top() left += geo.left() parent = parent.parent() self.move(round(left), top) @Slot(QModelIndex, QModelIndex) def current_item_changed(self, current, previous): """Handle item selection.""" self.sig_item_changed.emit(self.current_item()) # --- Qt overrides # ------------------------------------------------------------------------ @Slot() @Slot(QListWidgetItem) def enter(self, itemClicked=None): """Override Qt method.""" row = self.current_row() model_index = self.proxy.mapToSource(self.proxy.index(row, 0)) item = self.model.item(model_index.row()) if item: mode = self._mode_on self.sig_item_selected.emit(item, mode, self.search_text()[len(mode):]) def accept(self): """Override Qt method.""" super(Switcher, self).accept() def reject(self): """Override Qt method.""" self.set_search_text('') self.sig_rejected.emit() super(Switcher, self).reject() def resizeEvent(self, event): """Override Qt method.""" super(Switcher, self).resizeEvent(event) # --- Helper methods: Lineedit widget def search_text(self): """Get the normalized (lowecase) content of the search text.""" return to_text_string(self.edit.text()).lower() def set_search_text(self, string): """Set the content of the search text.""" self.edit.setText(string) # --- Helper methods: List widget def _is_separator(self, item): """Check if item is an separator item (SwitcherSeparatorItem).""" return isinstance(item, SwitcherSeparatorItem) def _select_row(self, steps): """Select row in list widget based on a number of steps with direction. Steps can be positive (next rows) or negative (previous rows). """ row = self.current_row() + steps if 0 <= row < self.count(): self.set_current_row(row) def count(self): """Get the item count in the list widget.""" return self.proxy.rowCount() def current_row(self): """Return the current selected row in the list widget.""" return self.list.currentIndex().row() def current_item(self): """Return the current selected item in the list widget.""" row = self.current_row() model_index = self.proxy.mapToSource(self.proxy.index(row, 0)) item = self.model.item(model_index.row()) return item def set_current_row(self, row): """Set the current selected row in the list widget.""" proxy_index = self.proxy.index(row, 0) selection_model = self.list.selectionModel() # https://doc.qt.io/qt-5/qitemselectionmodel.html#SelectionFlag-enum selection_model.setCurrentIndex( proxy_index, selection_model.ClearAndSelect) # Ensure that the selected item is visible self.list.scrollTo(proxy_index, QAbstractItemView.EnsureVisible) def previous_row(self): """Select previous row in list widget.""" steps = 1 prev_row = self.current_row() - steps if prev_row == -1: self.set_current_row(self.count() - 1) else: if prev_row >= 0: # Need to map the filtered list to the actual model items list_index = self.proxy.index(prev_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if self._is_separator(item): steps += 1 self._select_row(-steps) def next_row(self): """Select next row in list widget.""" steps = 1 next_row = self.current_row() + steps # Need to map the filtered list to the actual model items list_index = self.proxy.index(next_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if next_row >= self.count(): self.set_current_row(0) else: if item: if self._is_separator(item): steps += 1 self._select_row(steps)
class PathFinder(QDialog): """Search path of files in the folder.""" _MIN_WIDTH = 800 _MAX_HEIGHT = 600 def __init__(self, folder, parent=None): """Init.""" super().__init__(parent) font = get_font() self.folder = folder self.path_selected = "" self.path_list = [] self.results_old = {} self.setWindowTitle("Path Finder") self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint) self.setWindowOpacity(0.95) self.setFixedHeight(self._MAX_HEIGHT) self.setFont(font) # Set List widget self.list_viewer = QListView(self) self.list_viewer.setAttribute(Qt.WA_TransparentForMouseEvents) self.list_viewer.setFocusPolicy(Qt.NoFocus) self.list_viewer.setFixedWidth(self._MIN_WIDTH) self.list_viewer.setUniformItemSizes(True) self.list_model = QStringListModel() self.list_viewer.setModel(self.list_model) self.list_viewer.setFont(font) # Set edit self.edit = PathFinderEdit(self, textChanged=self.update_list) self.edit.setFont(font) self.edit.sig_esc_key_pressed.connect(self.close) self.edit.sig_enter_key_pressed.connect(self.enter) self.edit.sig_up_key_pressed.connect(lambda: self.prev_row(1)) self.edit.sig_pg_up_key_pressed.connect(self.pg_up) self.edit.sig_pg_half_up_key_pressed.connect(self.pg_half_up) self.edit.sig_down_key_pressed.connect(lambda: self.next_row(1)) self.edit.sig_pg_down_key_pressed.connect(self.pg_down) self.edit.sig_pg_half_down_key_pressed.connect(self.pg_half_down) layout = QVBoxLayout() layout.addWidget(self.edit) layout.addWidget(self.list_viewer) self.setLayout(layout) self.get_path_list() self.update_list() self.edit.setFocus() def get_path_selected(self): """Get path selected.""" return self.path_selected def get_number_of_visible_lines(self): """Get the number of visible lines in list.""" num_lines = 0 lv = self.list_viewer height = lv.visualRect(lv.model().index(0, 0)).height() if height > 0: num_lines = lv.viewport().height() // height return num_lines def get_path_list(self): """Get path of files including subdiretorys.""" if self.folder is None or not osp.isdir(self.folder): self.edit.setPlaceholderText("The project is not valid.") else: dir_ = QDir(self.folder) it = QDirIterator( self.folder, ['*.py', '*.txt', '*.md'], QDir.Files | QDir.NoDotAndDotDot | QDir.NoSymLinks, QDirIterator.Subdirectories) while it.hasNext(): self.path_list.append(dir_.relativeFilePath(it.next())) self.results_old[''] = self.path_list def update_list(self): """Update listview.""" query = self.edit.text() query = query.replace(" ", '') paths = self.results_old.get(query, None) if paths is None: collections = self.results_old.get(query[:-1], self.path_list) paths = fuzzyfinder(query, collections) if paths: self.list_model.setStringList(paths) self.list_viewer.setCurrentIndex(self.list_model.index(0)) def prev_row(self, stride=1): """Select prev row in list viewer.""" prev_row = self.list_viewer.currentIndex().row() - stride prev_row = max([prev_row, 0]) self.list_viewer.setCurrentIndex(self.list_model.index(prev_row)) def next_row(self, stride=1): """Select next row in list viewer.""" n_row = self.list_model.rowCount() if n_row == 0: return next_row = self.list_viewer.currentIndex().row() + stride next_row = min([next_row, n_row - 1]) self.list_viewer.setCurrentIndex(self.list_model.index(next_row)) def pg_up(self): """Scroll windows 1page backwards.""" n_line = self.get_number_of_visible_lines() self.prev_row(n_line) def pg_down(self): """Scroll windows 1page forwards.""" n_line = self.get_number_of_visible_lines() self.next_row(n_line) def pg_half_up(self): """Scroll windows half page backwards.""" n_line = self.get_number_of_visible_lines() self.prev_row(n_line // 2) def pg_half_down(self): """Scroll windows half page forwards.""" n_line = self.get_number_of_visible_lines() self.next_row(n_line // 2) def enter(self): """Select next row in list viewer.""" idx = self.list_viewer.currentIndex() rel_path = idx.data(Qt.DisplayRole) if rel_path and isinstance(self.folder, str): path = osp.join(self.folder, rel_path) self.path_selected = path self.close()
class DataTypeKeysWidget(QWidget): dataTypeKeySelected = Signal() def __init__(self, key_defs): QWidget.__init__(self) self.__filter_popup = FilterPopup(self, key_defs) self.__filter_popup.filterSettingsChanged.connect(self.onItemChanged) layout = QVBoxLayout() self.model = DataTypeKeysListModel(key_defs) self.filter_model = DataTypeProxyModel(self, self.model) filter_layout = QHBoxLayout() self.search_box = SearchBox() self.search_box.filterChanged.connect(self.setSearchString) filter_layout.addWidget(self.search_box) filter_popup_button = QToolButton() filter_popup_button.setIcon(resourceIcon("filter_list.svg")) filter_popup_button.clicked.connect(self.showFilterPopup) filter_layout.addWidget(filter_popup_button) layout.addLayout(filter_layout) self.data_type_keys_widget = QListView() self.data_type_keys_widget.setModel(self.filter_model) self.data_type_keys_widget.selectionModel().selectionChanged.connect( self.itemSelected) layout.addSpacing(15) layout.addWidget(self.data_type_keys_widget, 2) layout.addStretch() layout.addWidget( Legend("Observations available", DataTypeKeysListModel.HAS_OBSERVATIONS)) self.setLayout(layout) def onItemChanged(self, item): # self.filter_model.setShowBlockKeys(item["block"]) for value, visible in item.items(): self.filter_model.setFilterOnMetadata("data_origin", value, visible) def itemSelected(self): selected_item = self.getSelectedItem() if selected_item is not None: self.dataTypeKeySelected.emit() def getSelectedItem(self): """@rtype: str""" index = self.data_type_keys_widget.currentIndex() source_index = self.filter_model.mapToSource(index) item = self.model.itemAt(source_index) return item def selectDefault(self): self.data_type_keys_widget.setCurrentIndex( self.filter_model.index(0, 0)) def setSearchString(self, filter): self.filter_model.setFilterFixedString(filter) def showFilterPopup(self): self.__filter_popup.show()
class BibleReadingPlan(QWidget): template = { # Source / credits of the following plan: https://www.biblica.com/resources/reading-plans/ 1: [False, "Genesis 1, Genesis 2:1-17, Matthew 1:1-25, Psalm 1:1-6"], 2: [ False, "Genesis 2:18-25, Genesis 3, Genesis 4:1-16, Matthew 2:1-18, Psalm 2:1-12" ], 3: [ False, "Genesis 4:17-26, Genesis 5, Genesis 6, Matthew 2:19-23, Matthew 3, Psalm 3:1-8" ], 4: [ False, "Genesis 7, Genesis 8, Genesis 9:1-17, Matthew 4:1-22, Proverbs 1:1-7" ], 5: [ False, "Genesis 9:18-29, Genesis 10, Genesis 11:1-9, Matthew 4:23-25, Matthew 5:1-20, Psalm 4:1-8" ], 6: [ False, "Genesis 11:10-32, Genesis 12, Genesis 13, Matthew 5:21-42, Psalm 5:1-12" ], 7: [ False, "Genesis 14, Genesis 15, Genesis 16, Matthew 5:43-48, Matthew 6:1-24, Psalm 6" ], 8: [ False, "Genesis 17, Genesis 18, Matthew 6:25-34, Matthew 7:1-23, Proverbs 1:8-19" ], 9: [ False, "Genesis 19, Genesis 20:1-18, Matthew 7:24-29, Matthew 8:1-22, Psalm 7:1-9" ], 10: [ False, "Genesis 21, Genesis 22, Genesis 23, Matthew 8:23-34, Matthew 9:1-13, Psalm 7:10-17" ], 11: [False, "Genesis 24:1-67, Matthew 9:14-38, Psalm 8:1-9"], 12: [False, "Genesis 25, Genesis 26, Matthew 10:1-31, Proverbs 1:20-33"], 13: [ False, "Genesis 27, Genesis 28:1-22, Matthew 10:32-42, Matthew 11:1-15, Psalm 9:1-6" ], 14: [False, "Genesis 29, Genesis 30, Matthew 11:16-30, Psalm 9:7-12"], 15: [False, "Genesis 31:1-55, Matthew 12:1-21, Psalm 9:13-20"], 16: [False, "Genesis 32, Genesis 33, Matthew 12:22-45, Proverbs 2:1-11"], 17: [ False, "Genesis 34, Genesis 35, Matthew 12:46-50, Matthew 13:1-17, Psalm 10:1-11" ], 18: [False, "Genesis 36, Genesis 37, Matthew 13:18-35, Psalm 10:12-18"], 19: [False, "Genesis 38, Genesis 39, Matthew 13:36-58, Psalm 11:1-7"], 20: [ False, "Genesis 40, Genesis 41:1-40, Matthew 14:1-21, Proverbs 2:12-22" ], 21: [ False, "Genesis 41:41-57, Genesis 42, Matthew 14:22-36, Matthew 15:1-9, Psalm 12:1-8" ], 22: [False, "Genesis 43, Genesis 44, Matthew 15:10-39, Psalm 13:1-6"], 23: [ False, "Genesis 45, Genesis 46, Genesis 47:1-12, Matthew 16:1-20, Psalm 14:1-7" ], 24: [ False, "Genesis 47:13-31, Genesis 48, Matthew 16:21-28, Matthew 17:1-13, Proverbs 3:1-10" ], 25: [ False, "Genesis 49, Genesis 50, Matthew 17:14-27, Matthew 18:1-9, Psalm 15:1-5" ], 26: [False, "Job 1, Job 2, Job 3, Matthew 18:10-35, Psalm 16:1-11"], 27: [False, "Job 4, Job 5, Job 6, Job 7, Matthew 19:1-15, Psalm 17:1-5"], 28: [False, "Job 8, Job 9, Job 10, Matthew 19:16-30, Proverbs 3:11-20"], 29: [ False, "Job 11, Job 12, Job 13, Job 14, Matthew 20:1-19, Psalm 17:6-12" ], 30: [ False, "Job 15, Job 16, Job 17, Job 18, Matthew 20:20-34, Psalm 17:13-15" ], 31: [False, "Job 19, Job 20, Job 21, Matthew 21:1-17, Psalm 18:1-6"], 32: [False, "Job 22, Job 23, Job 24, Matthew 21:18-32, Proverbs 3:21-35"], 33: [ False, "Job 25, Job 26, Job 27, Job 28, Job 29, Matthew 21:33-46, Matthew 22:1-14, Psalm 18:7-15" ], 34: [False, "Job 30, Job 31, Job 32, Matthew 22:15-46, Psalm 18:16-24"], 35: [False, "Job 33, Job 34, Matthew 23:1-39, Psalm 18:25-36"], 36: [False, "Job 35, Job 36, Job 37, Matthew 24:1-31, Proverbs 4:1-9"], 37: [ False, "Job 38, Job 39, Job 40:1-2, Matthew 24:32-51, Matthew 25:1-13, Psalm 18:37-42" ], 38: [ False, "Job 40:3-24, Job 41, Job 42, Matthew 25:14-46, Psalm 18:43-50" ], 39: [False, "Exodus 1, Exodus 2, Exodus 3, Matthew 26:1-30, Psalm 19:1-6"], 40: [ False, "Exodus 4, Exodus 5, Exodus 6:1-12, Matthew 26:31-46, Proverbs 4:10-19" ], 41: [ False, "Exodus 6:13-30, Exodus 7,Exodus 8, Matthew 26:47-68, Psalm 19:7-14" ], 42: [ False, "Exodus 9, Exodus 10, Matthew 26:69-75, Matthew 27:1-10, Psalm 20:1-9" ], 43: [False, "Exodus 11, Exodus 12, Matthew 27:11-44, Psalm 21:1-7"], 44: [False, "Exodus 13, Exodus 14, Matthew 27:45-66, Proverbs 4:20-27"], 45: [False, "Exodus 15, Exodus 16, Matthew 28:1-20, Psalm 21:8-13"], 46: [False, "Exodus 17, Exodus 18, Mark 1:1-28, Psalm 22:1-11"], 47: [ False, "Exodus 19, Exodus 20, Mark 1:29-45, Mark 2:1-17, Psalm 22:12-21" ], 48: [ False, "Exodus 21, Exodus 22, Mark 2:18-27, Mark 3:1-30, Proverbs 5:1-14" ], 49: [ False, "Exodus 23, Exodus 24, Mark 3:31-35, Mark 4:1-29, Psalm 22:22-31" ], 50: [ False, "Exodus 25, Exodus 26, Mark 4:30-41, Mark 5:1-20, Psalm 23:1-6" ], 51: [ False, "Exodus 27, Exodus 28, Mark 5:21-43, Mark 6:1-6, Psalm 24:1-10" ], 52: [False, "Exodus 29, Exodus 30, Mark 6:7-29, Proverbs 5:15-23"], 53: [ False, "Exodus 31, Exodus 32, Exodus 33:1-6, Mark 6:30-56, Psalm 25:1-7" ], 54: [False, "Exodus 33:7-23, Exodus 34, Mark 7:1-30, Psalm 25:8-15"], 55: [ False, "Exodus 35, Exodus 36, Mark 7:31-37, Mark 8:1-13, Psalm 25:16-22" ], 56: [ False, "Exodus 37, Exodus 38, Mark 8:14-38, Mark 9:1, Proverbs 6:1-11" ], 57: [False, "Exodus 39, Exodus 40, Mark 9:2-32, Psalm 26:1-12"], 58: [ False, "Leviticus 1, Leviticus 2, Leviticus 3, Mark 9:33-50, Mark 10:1-12, Psalm 27:1-6" ], 59: [False, "Leviticus 4, Leviticus 5:1-13, Mark 10:13-31, Psalm 27:7-14"], 60: [ False, "Leviticus 5:14-19, Leviticus 6, Leviticus 7:1-10, Mark 10:32-52, Proverbs 6:12-19" ], 61: [False, "Leviticus 7:11-38, Leviticus 8, Mark 11:1-27, Psalm 28"], 62: [ False, "Leviticus 9, Leviticus 10, Mark 11:28-33, Mark 12:1-12, Psalm 29" ], 63: [False, "Leviticus 11, Leviticus 12, Mark 12:13-27, Psalm 30:1-7"], 64: [False, "Leviticus 13:1-59, Mark 12:28-44, Proverbs 6:20-29"], 65: [False, "Leviticus 14:1-57, Mark 13:1-31, Psalm 30:8-12"], 66: [ False, "Leviticus 15, Leviticus 16, Mark 13:32-37, Mark 14:1-16, Psalm 31:1-8" ], 67: [False, "Leviticus 17, Leviticus 18, Mark 14:17-42, Psalm 31:9-18"], 68: [False, "Leviticus 19, Leviticus 20, Mark 14:43-72, Proverbs 6:30-35"], 69: [ False, "Leviticus 21, Leviticus 22, Mark 15:1-32, Psalm 31:19-24" ], 70: [False, "Leviticus 23, Leviticus 24, Mark 15:33-47, Psalm 32"], 71: [ False, "Leviticus 25, Leviticus 26:1-13, Mark 16:1-20, Psalm 33:1-11" ], 72: [ False, "Leviticus 26:14-46, Leviticus 27, Luke 1:1-25, Proverbs 7:1-5" ], 73: [False, "Numbers 1, Numbers 2:1-9, Luke 1:26-38, Psalm 33:12-22"], 74: [False, "Numbers 2:10-34, Numbers 3, Luke 1:39-56, Psalm 34:1-10"], 75: [False, "Numbers 4, Numbers 5:1-10, Luke 1:57-80, Psalm 34:11-22"], 76: [ False, "Numbers 5:11-31, Numbers 6:1-27, Luke 2:1-20, Proverbs 7:6-20" ], 77: [False, "Numbers 7:1-65, Luke 2:21-40, Psalm 35:1-10"], 78: [ False, "Numbers 7:66-89, Numbers 8, Numbers 9:1-14, Luke 2:41-52, Psalm 35:11-18" ], 79: [ False, "Numbers 9:15-23, Numbers 10, Numbers 11:1-3, Luke 3:1-22, Psalm 35:19-28" ], 80: [ False, "Numbers 11:4-35, Numbers 12, Numbers 13:1-25, Luke 3:23-38, Luke 4:1-13, Proverbs 7:21-27" ], 81: [ False, "Numbers 13:26-33, Numbers 14, Luke 4:14-37, Psalm 36:1-12" ], 82: [ False, "Numbers 15, Numbers 16:1-35, Luke 4:38-44, Luke 5:1-16, Psalm 37:1-9" ], 83: [ False, "Numbers 16:36-50, Numbers 17, Numbers 18, Luke 5:17-32, Psalm 37:10-20" ], 84: [ False, "Numbers 19, Numbers 20, Numbers 21:1-3, Luke 5:33-39, Luke 6:1-11, Proverbs 8:1-11" ], 85: [ False, "Numbers 21:4-35, Numbers 22:1-20, Luke 6:12-36, Psalm 37:21-31" ], 86: [ False, "Numbers 22:21-41, Numbers 23:1-26, Luke 6:37-49, Luke 7:1-10, Psalm 37:32-40" ], 87: [ False, "Numbers 23:27-30, Numbers 24, Numbers 25, Luke 7:11-35, Psalm 38:1-11" ], 88: [False, "Numbers 26, Numbers 27:1-11, Luke 7:36-50, Proverbs 8:12-21"], 89: [ False, "Numbers 27:12-23, Numbers 28, Numbers 29:1-11, Luke 8:1-18, Psalm 38:12-22" ], 90: [ False, "Numbers 29:12-40, Numbers 30, Numbers 31:1-24, Luke 8:19-39, Psalm 39:1-13" ], 91: [ False, "Numbers 31:25-54, Numbers 32, Luke 8:40-56, Luke 9:1-9, Psalm 40:1-8" ], 92: [False, "Numbers 33, Numbers 34, Luke 9:10-27, Proverbs 8:22-31"], 93: [ False, "Numbers 35, Numbers 36:1-12, Luke 9:28-56, Psalm 40:9-17" ], 94: [ False, "Deuteronomy 1, Deuteronomy 2:1-23, Luke 9:57-62, Luke 10:1-24, Psalm 41:1-6" ], 95: [ False, "Deuteronomy 2:24-37, Deuteronomy 3, Deuteronomy 4:1-14, Luke 10:25-42, Luke 11:1-4, Psalm 41:7-13" ], 96: [ False, "Deuteronomy 4:15-49, Deuteronomy 5, Luke 11:5-32, Proverbs 8:32-36" ], 97: [ False, "Deuteronomy 6, Deuteronomy 7, Deuteronomy 8, Luke 11:33-54, Psalm 42:1-6" ], 98: [ False, "Deuteronomy 9, Deuteronomy 10, Luke 12:1-34, Psalm 42:7-11" ], 99: [False, "Deuteronomy 11, Deuteronomy 12, Luke 12:35-59, Psalm 43:1-5"], 100: [ False, "Deuteronomy 13, Deuteronomy 14, Luke 13:1-30, Proverbs 9:1-12" ], 101: [ False, "Deuteronomy 15, Deuteronomy 16:1-20, Luke 13:31-35, Luke 14:1-14, Psalm 44:1-12" ], 102: [ False, "Deuteronomy 16:21-22, Deuteronomy 17, Deuteronomy 18, Luke 14:15-35, Psalm 44:13-26" ], 103: [ False, "Deuteronomy 19, Deuteronomy 20, Luke 15:1-32, Psalm 45:1-9" ], 104: [ False, "Deuteronomy 21, Deuteronomy 22, Luke 16:1-18, Proverbs 9:13-18" ], 105: [ False, "Deuteronomy 23, Deuteronomy 24, Deuteronomy 25:1-19, Luke 16:19-31, Luke 17:1-10, Psalm 45:10-17" ], 106: [ False, "Deuteronomy 26, Deuteronomy 27, Deuteronomy 28:1-14, Luke 17:11-37, Psalm 46:1-11" ], 107: [False, "Deuteronomy 28:15-68, Luke 18:1-30, Psalm 47:1-9"], 108: [ False, "Deuteronomy 29, Deuteronomy 30:1-10, Luke 18:31-43, Luke 19:1-10, Proverbs 10:1-10" ], 109: [ False, "Deuteronomy 30:11-20, Deuteronomy 31:1-29, Luke 19:11-44, Psalm 48:1-8" ], 110: [ False, "Deuteronomy 31:30, Deuteronomy 32, Luke 19:45-48, Luke 20:1-26, Psalm 48:9-14" ], 111: [ False, "Deuteronomy 33, Deuteronomy 34:1-12, Luke 20:27-47, Luke 21:1-4, Psalm 49:1-20" ], 112: [False, "Joshua 1, Joshua 2, Luke 21:5-38, Proverbs 10:11-20"], 113: [ False, "Joshua 3, Joshua 4, Joshua 5:1-12, Luke 22:1-38, Psalm 50:1-15" ], 114: [ False, "Joshua 5:13-15, Joshua 6, Joshua 7, Luke 22:39-62, Psalm 50:16-23" ], 115: [ False, "Joshua 8, Joshua 9:1-15, Luke 22:63-71, Luke 23:1-25, Psalm 51:1-9" ], 116: [ False, "Joshua 9:16-27, Joshua 10, Luke 23:26-56, Proverbs 10:21-30" ], 117: [False, "Joshua 11, Joshua 12, Luke 24:1-35, Psalm 51:10-19"], 118: [False, "Joshua 13, Joshua 14, Luke 24:36-53, Psalm 52:1-9"], 119: [False, "Joshua 15, Joshua 16, John 1:1-28, Psalm 53:1-6"], 120: [ False, "Joshua 17, Joshua 18, John 1:29-51, Proverbs 10:31-32, Proverbs 11:1-8" ], 121: [ False, "Joshua 19, Joshua 20, Joshua 21:1-19, John 2:1-25, Psalm 54:1-7" ], 122: [False, "Joshua 21:20-45, Joshua 22, John 3:1-21, Psalm 55:1-11"], 123: [False, "Joshua 23, Joshua 24, John 3:22-36, Psalm 55:12-23"], 124: [False, "Judges 1, Judges 2:1-5, John 4:1-26, Proverbs 11:9-18"], 125: [False, "Judges 2:6-23, Judges 3, John 4:27-42, Psalm 56:1-13"], 126: [ False, "Judges 4, Judges 5, John 4:43-54, John 5:1-15, Psalm 57:1-6" ], 127: [False, "Judges 6, Judges 7:1-8, John 5:16-30, Psalm 57:7-11"], 128: [ False, "Judges 7:8-25, Judges 8, John 5:31-47, Proverbs 11:19-28" ], 129: [False, "Judges 9, John 6:1-24, Psalm 58:1-11"], 130: [False, "Judges 10, Judges 11, John 6:25-59, Psalm 59:1-8"], 131: [ False, "Judges 12, Judges 13, John 6:60-71, John 7:1-13, Psalm 59:9-19" ], 132: [ False, "Judges 14, Judges 15, John 7:14-44, Proverbs 11:29-31, Proverbs 12:1-7" ], 133: [ False, "Judges 16, Judges 17, John 7:45-53, John 8:1-11, Psalm 60:1-4" ], 134: [False, "Judges 18, Judges 19, John 8:12-30, Psalm 60:5-12"], 135: [False, "Judges 20, Judges 21, John 8:31-59, Psalm 61:1-8"], 136: [False, "Ruth 1, Ruth 2, John 9:1-34, Proverbs 12:8-17"], 137: [ False, "Ruth 3, Ruth 4, John 9:35-41, John 10:1-21, Psalm 62:1-12" ], 138: [ False, "1 Samuel 1, 1 Samuel 2:1-26, John 10:22-42, Psalm 63:1-11" ], 139: [ False, "1 Samuel 2:27-36, 1 Samuel 3, 1 Samuel 4, John 11:1-44, Psalm 64:1-10" ], 140: [ False, "1 Samuel 5, 1 Samuel 6, 1 Samuel 7, John 11:45-57, John 12:1-11, Proverbs 12:18-27" ], 141: [ False, "1 Samuel 8, 1 Samuel 9, 1 Samuel 10:1-8, John 12:12-26, Psalm 65:1-13" ], 142: [ False, "1 Samuel 10:9-27, 1 Samuel 11, 1 Samuel 12, John 12:37-50, John 13:1-17, Psalm 66:1-12" ], 143: [ False, "1 Samuel 13, 1 Samuel 14:1-23, John 13:18-38, Psalm 66:13-20" ], 144: [ False, "1 Samuel 14:24-52, 1 Samuel 15, John 14:1-31, Proverbs 12:28, Proverbs 13:1-9" ], 145: [ False, "1 Samuel 16, 1 Samuel 17:1-37, John 15, John 16:1-4, Psalm 67:1-7" ], 146: [ False, "1 Samuel 17:38-58, 1 Samuel 18, John 16:5-33, John 17:1-5, Psalm 68:1-6" ], 147: [False, "1 Samuel 19, 1 Samuel 20, John 17:6-26, Psalm 68:7-14"], 148: [ False, "1 Samuel 21, 1 Samuel 22, 1 Samuel 23, John 18:1-24, Proverbs 13:10-19" ], 149: [ False, "1 Samuel 24, 1 Samuel 25, John 18:25-40, Psalm 68:15-20" ], 150: [ False, "1 Samuel 26, 1 Samuel 27, 1 Samuel 28, John 19:1-27, Psalm 68:21-27" ], 151: [ False, "1 Samuel 29, 1 Samuel 30, 1 Samuel 31, John 19:28-42, John 20:1-9, Psalm 68:28-35" ], 152: [ False, "2 Samuel 1, 2 Samuel 2:1-7, John 20:10-31, Proverbs 13:20-25, Proverbs 14:1-4" ], 153: [ False, "2 Samuel 2:8-32, 2 Samuel 3:1-21, John 21:1-25, Psalm 69:1-12" ], 154: [ False, "2 Samuel 3:22-39, 2 Samuel 4, 2 Samuel 5:1-5, Acts 1:1-22, Psalm 69:13-28" ], 155: [ False, "2 Samuel 5:6-25, 2 Samuel 6, Acts 1:23-26, Acts 2:1-21, Psalm 69:29-36" ], 156: [False, "2 Samuel 7, 2 Samuel 8, Acts 2:22-47, Proverbs 14:4-14"], 157: [False, "2 Samuel 9, 2 Samuel 10, Acts 3, Psalm 70:1-5"], 158: [False, "2 Samuel 11, 2 Samuel 12, Acts 4:1-22, Psalm 71:1-8"], 159: [False, "2 Samuel 13, Acts 4:23-37, Acts 5:1-11, Psalm 71:9-18"], 160: [ False, "2 Samuel 14, 2 Samuel 15:1-12, Acts 5:12-42, Proverbs 14:15-24" ], 161: [ False, "2 Samuel 15:13-37, 2 Samuel 16:1-14, Acts 6, Acts 7:1-19, Psalm 71:19-24" ], 162: [ False, "2 Samuel 16:15-23, 2 Samuel 17, 2 Samuel 18:1-18, Acts 7:20-43, Psalm 72:1-20" ], 163: [ False, "2 Samuel 18:19-33, 2 Samuel 19, Acts 7:44-60, Acts 8:1-3, Psalm 73:1-14" ], 164: [ False, "2 Samuel 20, 2 Samuel 21, Acts 8:4-40, Proverbs 14:25-35" ], 165: [ False, "2 Samuel 22, 2 Samuel 23:1-7, Acts 9:1-31, Psalm 73:15-28" ], 166: [ False, "2 Samuel 23:8-39, 2 Samuel 24:1-25, Acts 9:32-43, Acts 10:1-23, Psalms 74:1-9" ], 167: [ False, "1 Kings 1, 1 Kings 2:1-12, Acts 10:23-48, Acts 11:1-18, Psalm 74:10-17" ], 168: [ False, "1 Kings 2:13-46, 1 Kings 3:1-15, Acts 11:19-30, Acts 12:1-19, Proverbs 15:1-10" ], 169: [ False, "1 Kings 3:16-28, 1 Kings 4, 1 Kings 5, Acts 12:19-25, Acts 13:1-12, Psalm 74:18-23" ], 170: [ False, "1 Kings 6, 1 Kings 7:1-22, Acts 13:13-41, Psalm 75:1-10" ], 171: [ False, "1 Kings 7:23-51, 1 Kings 8:1-21, Acts 13:42-52, Acts 14:1-7, Psalm 76:1-12" ], 172: [ False, "1 Kings 8:22-66, 1 Kings 9:1-9, Acts 14:8-28, Proverbs 15:11-20" ], 173: [ False, "1 Kings 9:10-28, 1 Kings 10, 1 Kings 11:1-13, Acts 15:1-21, Psalm 77:1-9" ], 174: [ False, "1 Kings 11:14-43, 1 Kings 12:1-24, Acts 15:22-41, Psalm 77:10-20" ], 175: [ False, "1 Kings 12:25-33, 1 Kings 13, 1 Kings 14:1-20, Acts 16:1-15, Psalm 78:1-8" ], 176: [ False, "1 Kings 14:21-31, 1 Kings 15, 1 Kings 16:1-7, Acts 16:16-40, Proverbs 15:21-30" ], 177: [ False, "1 Kings 16:8-34, 1 Kings 17, 1 Kings 18:1-15, Acts 17:1-21, Psalm 78:9-16" ], 178: [ False, "1 Kings 18:16-46, 1 Kings 19, Acts 17:22-34, Acts 18:1-8, Psalm 78:17-31" ], 179: [ False, "1 Kings 20, 1 Kings 21, Acts 18:9-28, Acts 19:1-13, Psalm 78:32-39" ], 180: [ False, "1 Kings 22:1-53, Acts 19:14-41, Proverbs 15:31-33, Proverbs 16:1-7" ], 181: [ False, "2 Kings 1, 2 Kings 2:1-25, Acts 20:1-38, Psalm 78:40-55" ], 182: [ False, "2 Kings 3, 2 Kings 4:1-37, Acts 21:1-26, Psalm 78:56-72" ], 183: [ False, "2 Kings 4:38-44, 2 Kings 5, 2 Kings 6:1-23, Acts 21:27-40, Acts 22:1-22, Psalm 79:1-13" ], 184: [ False, "2 Kings 6:24-33, 2 Kings 7, 2 Kings 8:1-15, Acts 22:22-30, Acts 23:1-11, Proverbs 16:8-17" ], 185: [ False, "2 Kings 8:16-29, 2 Kings 9, Acts 23:12-35, Psalm 80:1-7" ], 186: [False, "2 Kings 10, 2 Kings 11, Acts 24:1-27, Psalm 80:8-19"], 187: [ False, "2 Kings 12, 2 Kings 13, 2 Kings 14:1-22, Acts 25:1-22, Psalm 81:1-7" ], 188: [ False, "2 Kings 14:23-29, 2 Kings 15, Acts 25:23-27, Acts 26:1-23, Proverbs 16:18-27" ], 189: [ False, "2 Kings 16, 2 Kings 17, Acts 26:24-32, Acts 27:1-12, Psalm 81:8-16" ], 190: [ False, "2 Kings 18, 2 Kings 19:1-13, Acts 27:13-44, Psalm 82:1-8" ], 191: [ False, "2 Kings 19:14-37, 2 Kings 20, Acts 28:1-16, Psalm 83:1-18" ], 192: [ False, "2 Kings 21, 2 Kings 22, Acts 28:17-31, Proverbs 16:28-33, Proverbs 17:1-4" ], 193: [ False, "2 Kings 23, 2 Kings 24:1-7, Romans 1:1-17, Psalm 84:1-7" ], 194: [ False, "2 Kings 24:8-20, 2 Kings 25, Romans 1:18-32, Psalm 84:8-12" ], 195: [ False, "Jonah 1, Jonah 2, Jonah 3, Jonah 4, Romans 2:1-16, Psalm 85:1-7" ], 196: [ False, "Amos 1, Amos 2, Romans 2:17-29, Romans 3:1-8, Proverbs 17:5-14" ], 197: [False, "Amos 3, Amos 4, Romans 3:9-31, Psalm 85:8-13"], 198: [False, "Amos 5, Romans 4:1-15, Psalm 86:1-10"], 199: [ False, "Amos 6, Amos 7, Romans 4:16-25, Romans 5:1-11, Psalm 86:11-17" ], 200: [False, "Amos 8, Amos 9, Romans 5:12-21, Proverbs 17:15-24"], 201: [False, "Hosea 1, Hosea 2, Romans 6:1-14, Psalm 87:1-7"], 202: [ False, "Hosea 3, Hosea 4, Hosea 5, Romans 6:15-23, Romans 7:1-6, Psalm 88:1-9" ], 203: [False, "Hosea 6, Hosea 7, Romans 7:7-25, Psalm 88:9-18"], 204: [ False, "Hosea 8, Hosea 9, Romans 8:1-17, Proverbs 17:25-28, Proverbs 18:1-6" ], 205: [False, "Hosea 10, Hosea 11, Romans 8:18-39, Psalm 89:1-8"], 206: [ False, "Hosea 11, Hosea 12, Hosea 13, Hosea 14, Romans 9:1-21, Psalm 89:9-13" ], 207: [ False, "1 Chronicles 1, 1 Chronicles 2:1-17, Romans 9:22-33, Romans 10:1-4, Psalm 89:14-18" ], 208: [ False, "1 Chronicles 2:18-55, 1 Chronicles 3, 1 Chronicles 4:1-8, Romans 10:5-21, Romans 11:1-10, Proverbs 18:7-16" ], 209: [ False, "1 Chronicles 4:9-43, 1 Chronicles 5, Romans 11:11-32, Psalm 89:19-29" ], 210: [ False, "1 Chronicles 6, Romans 11:33-36, Romans 12:1-21, Psalm 89:30-37" ], 211: [ False, "1 Chronicles 7, 1 Chronicles 8, Romans 13:1-14, Psalm 89:38-45" ], 212: [ False, "1 Chronicles 9, 1 Chronicles 10:1-14, Romans 14:1-18, Proverbs 18:17-24, Proverbs 19:1-2" ], 213: [ False, "1 Chronicles 11, 1 Chronicles 12:1-22, Romans 14:19-23, Romans 15:1-13, Psalm 89:46-52" ], 214: [ False, "1 Chronicles 12:23-40, 1 Chronicles 13, 1 Chronicles 14, Romans 15:14-33, Psalm 90:1-10" ], 215: [ False, "1 Chronicles 15, 1 Chronicles 16:1-36, Romans 16, Psalm 90:11-17" ], 216: [ False, "1 Chronicles 16:37-43, 1 Chronicles 17, 1 Chronicles 18, 1 Corinthians 1:1-17, Proverbs 19:3-12" ], 217: [ False, "1 Chronicles 19, 1 Chronicles 20, 1 Chronicles 21, 1 Corinthians 1:18-31, 1 Corinthians 2:1-5, Psalm 91:1-8" ], 218: [ False, "1 Chronicles 22, 1 Chronicles 23, 1 Corinthians 2:6-16, Psalm 91:9-16" ], 219: [ False, "1 Chronicles 24, 1 Chronicles 25, 1 Chronicles 26:1-19, 1 Corinthians 3, Psalm 92:1-15" ], 220: [ False, "1 Chronicles 26:20-32, 1 Chronicles 27, 1 Corinthians 4, Proverbs 19:13-22" ], 221: [ False, "1 Chronicles 28, 1 Chronicles 29, 1 Corinthians 5, Psalm 93:1-5" ], 222: [False, "2 Chronicles 1:1-17, 1 Corinthians 6, Psalm 94:1-11"], 223: [ False, "Ecclesiastes 1, Ecclesiastes 2, Ecclesiastes 3:1-22, 1 Corinthians 7:1-16, Psalm 94:12-23" ], 224: [ False, "Ecclesiastes 4, Ecclesiastes 5, Ecclesiastes 6, 1 Corinthians 7:17-35, Proverbs 19:23-29, Proverbs 20:1-4" ], 225: [ False, "Ecclesiastes 7, Ecclesiastes 8, Ecclesiastes 9:1-12, 1 Corinthians 7:36-40, 1 Corinthians 8:1-13, Psalm 95:1-11" ], 226: [ False, "Ecclesiastes 9:13-18, Ecclesiastes 10, Ecclesiastes 11, Ecclesiastes 12, 1 Corinthians 9:1-18, Psalm 96:1-13" ], 227: [ False, "2 Chronicles 2, 2 Chronicles 3, 2 Chronicles 4, 2 Chronicles 5:1, 1 Corinthians 9:19-27, 1 Corinthians 10:1-13, Psalm 97:1-12" ], 228: [ False, "2 Chronicles 5:2-14, 2 Chronicles 6, 2 Chronicles 7:1-10, 1 Corinthians 10:14-33, 1 Corinthians 11:1, Proverbs 20:5-14" ], 229: [ False, "2 Chronicles 7:11-22, 2 Chronicles 8, 2 Chronicles 9, 1 Corinthians 11:2-34, Psalm 98:1-9" ], 230: [ False, "Song 1, Song 2, Song 3, Song 4, 1 Corinthians 12:1-26, Psalm 99:1-9" ], 231: [ False, "Song 5, Song 6, Song 7, Song 8, 1 Corinthians 12:27-31, 1 Corinthians 13:1-13, Psalm 100:1-5" ], 232: [ False, "2 Chronicles 10, 2 Chronicles 11, 2 Chronicles 12, 1 Corinthians 14:1-19, Proverbs 20:15-24" ], 233: [ False, "2 Chronicles 13, 2 Chronicles 14, 2 Chronicles 15, 1 Corinthians 14:20-40, Psalm 101:1-8" ], 234: [ False, "2 Chronicles 16, 2 Chronicles 17, 2 Chronicles 18:1-27, 1 Corinthians 15:1-34, Psalm 102:1-11" ], 235: [ False, "2 Chronicles 18:28-34, 2 Chronicles 19, 2 Chronicles 20, 1 Corinthians 15:35-49, Psalm 102:12-17" ], 236: [ False, "2 Chronicles 21, 2 Chronicles 22, 2 Chronicles 23, 1 Corinthians 15:50-58, 1 Corinthians 16:1-4, Proverbs 20:25-30, Proverbs 21:1-4" ], 237: [ False, "2 Chronicles 24, 2 Chronicles 25, 1 Corinthians 16:5-24, Psalm 102:18-28" ], 238: [ False, "2 Chronicles 26, 2 Chronicles 27, 2 Chronicles 28, 2 Corinthians 1:1-11, Psalm 103:1-12" ], 239: [ False, "2 Chronicles 29, 2 Chronicles 30, 2 Chronicles 31:1, 2 Corinthians 1:12-22, Psalm 103:13-22" ], 240: [ False, "2 Chronicles 31:2-21, 2 Chronicles 32, 2 Chronicles 33:1-20, 2 Corinthians 1:23, 2 Corinthians 2:1-11, Proverbs 21:5-16" ], 241: [ False, "2 Chronicles 33:21-24, 2 Chronicles 34, 2 Chronicles 35:1-19, 2 Corinthians 2:12-17, 2 Corinthians 3:1-6, Psalm 104:1-18" ], 242: [ False, "2 Chronicles 35:20-27, 2 Chronicles 36, 2 Corinthians 3:7-18, Psalm 104:19-30" ], 243: [ False, "Micah 1, Micah 2, Micah 3, Micah 4, 2 Corinthians 4, Psalm 104:31-35" ], 244: [ False, "Micah 5, Micah 6, Micah 7, 2 Corinthians 5:1-10, Proverbs 21:17-26" ], 245: [ False, "Isaiah 1, Isaiah 2, 2 Corinthians 5:11-21, 2 Corinthians 6:1-2, Psalm 105:1-11" ], 246: [ False, "Isaiah 3, Isaiah 4, Isaiah 5:1-7, 2 Corinthians 6:3-18, 2 Corinthians 7:1, Psalm 105:12-22" ], 247: [ False, "Isaiah 5:8-30, Isaiah 6, Isaiah 7, Isaiah 8:1-10, 2 Corinthians 7:2-16, Psalm 105:23-36" ], 248: [ False, "Isaiah 8:11-22, Isaiah 9, Isaiah 10:1-19, 2 Corinthians 8:1-15, Proverbs 21:27-31, Proverbs 22:1-6" ], 249: [ False, "Isaiah 10:20-34, Isaiah 11, Isaiah 12, Isaiah 13, 2 Corinthians 8:16-24, 2 Corinthians 9:1-5, Psalm 105:37-45" ], 250: [ False, "Isaiah 14, Isaiah 15, Isaiah 16, 2 Corinthians 9:6-15, Psalm 106:1-15" ], 251: [ False, "Isaiah 17, Isaiah 18, Isaiah 19, 2 Corinthians 10, Psalm 106:16-31" ], 252: [ False, "Isaiah 20, Isaiah 21, Isaiah 22, Isaiah 23, 2 Corinthians 11:1-15, Proverbs 22:7-16" ], 253: [ False, "Isaiah 24, Isaiah 25, Isaiah 26, 2 Corinthians 11:16-33, Psalm 106:32-39" ], 254: [ False, "Isaiah 27, Isaiah 28, 2 Corinthians 12:1-10, Psalm 106:40-48" ], 255: [ False, "Isaiah 29, Isaiah 30:1-18, 2 Corinthians 12:11-21, Psalm 107:1-9" ], 256: [ False, "Isaiah 30:19-33, Isaiah 31, Isaiah 32, 2 Corinthians 13, Proverbs 22:17-27" ], 257: [ False, "Isaiah 33, Isaiah 34, Isaiah 35, Galatians 1, Psalm 107:10-22" ], 258: [ False, "Isaiah 36, Isaiah 37, Galatians 2:1-10, Psalm 107:23-32" ], 259: [ False, "Isaiah 38, Isaiah 39, Isaiah 40, Galatians 2:11-21, Galatians 3:1-9, Psalm 107:33-43" ], 260: [ False, "Isaiah 41, Isaiah 42, Galatians 3:10-25, Proverbs 22:28-29, Proverbs 23:1-9" ], 261: [ False, "Isaiah 43, Isaiah 44:1-23, Galatians 3:26-29, Galatians 4:1-20, Psalm 108:1-5" ], 262: [ False, "Isaiah 44:24-28, Isaiah 45, Isaiah 46, Galatians 4:21-31, Galatians 5:1-6, Psalm 108:6-13" ], 263: [ False, "Isaiah 47, Isaiah 48, Isaiah 49:1-7, Galatians 5:7-26, Psalm 109:1-20" ], 264: [ False, "Isaiah 49:8-26, Isaiah 50, Isaiah 51:1-16, Galatians 6, Proverbs 23:10-18" ], 265: [ False, "Isaiah 51:17-23, Isaiah 52, Isaiah 53, Isaiah 54, Ephesians 1, Psalm 109:21-31" ], 266: [ False, "Isaiah 55, Isaiah 56, Isaiah 57:1-13, Ephesians 2, Psalm 110:1-7" ], 267: [ False, "Isaiah 57:14-21, Isaiah 58, Isaiah 59, Ephesians 3, Psalm 111:1-10" ], 268: [ False, "Isaiah 60, Isaiah 61, Isaiah 62, Ephesians 4:1-16, Proverbs 23:19-28" ], 269: [ False, "Isaiah 63, Isaiah 64, Isaiah 65:1-16, Ephesians 4:17-32, Ephesians 5:1-7, Psalm 112:1-10" ], 270: [ False, "Isaiah 65:17-25, Isaiah 66, Ephesians 5:8-33, Psalm 113:1-9" ], 271: [False, "Nahum 1, Nahum 2, Nahum 3, Ephesians 6, Psalm 114:1-8"], 272: [ False, "Zephaniah 1, Zephaniah 2, Zephaniah 3, Philippians 1:1-26, Proverbs 23:29-35, Proverbs 24:1-4" ], 273: [ False, "Jeremiah 1, Jeremiah 2:1-30, Philippians 1:27-30, Philippians 2:1-11, Psalm 115:1-11" ], 274: [ False, "Jeremiah 2:31-47, Jeremiah 3, Jeremiah 4:1-9, Philippians 2:12-30, Psalm 115:12-18" ], 275: [ False, "Jeremiah 4:10-31, Jeremiah 5, Philippians 3, Philippians 4:1, Psalm 116:1-11" ], 276: [ False, "Jeremiah 6, Jeremiah 7:1-29, Philippians 4:2-23, Proverbs 24:5-14" ], 277: [ False, "Jeremiah 7:30-34, Jeremiah 8, Jeremiah 9:1-16, Colossians 1:1-23, Psalm 116:12-19" ], 278: [ False, "Jeremiah 9:17-26, Jeremiah 10, Jeremiah 11:1-17, Colossians 1:24-29, Colossians 2:1-5, Psalm 117:1-2" ], 279: [ False, "Jeremiah 11:18-23, Jeremiah 12, Jeremiah 13, Colossians 2:6-23, Psalm 118:1-16" ], 280: [ False, "Jeremiah 14, Jeremiah 15, Colossians 3, Colossians 4:1, Proverbs 24:15-22" ], 281: [ False, "Jeremiah 16, Jeremiah 17, Colossians 4:2-18, Psalm 118:17-29" ], 282: [ False, "Jeremiah 18, Jeremiah 19, Jeremiah 20, 1 Thessalonians 1, 1 Thessalonians 2:1-16, Psalm 119:1-8" ], 283: [ False, "Jeremiah 21, Jeremiah 22, Jeremiah 23:1-8, 1 Thessalonians 2:17-19, 1 Thessalonians 3, Psalm 119:9-16" ], 284: [ False, "Jeremiah 23:9-40, Jeremiah 24, Jeremiah 25:1-14, 1 Thessalonians 4, Proverbs 24:23-34" ], 285: [ False, "Jeremiah 25:15-38, Jeremiah 26, 1 Thessalonians 5, Psalm 119:17-24" ], 286: [ False, "Jeremiah 27, Jeremiah 28, Jeremiah 29:1-23, 2 Thessalonians 1, Psalm 119:25-32" ], 287: [ False, "Jeremiah 29:24-32, Jeremiah 30, Jeremiah 31:1-14, 2 Thessalonians 2, Psalm 119:33-40" ], 288: [ False, "Jeremiah 31:15-40, Jeremiah 32:1-25, 2 Thessalonians 3, Proverbs 25:1-10" ], 289: [ False, "Jeremiah 32:26-44, Jeremiah 33, Jeremiah 34, 1 Timothy 1, Psalm 119:41-48" ], 290: [ False, "Jeremiah 35, Jeremiah 36, Jeremiah 37, 1 Timothy 2, Psalm 119:49-56" ], 291: [ False, "Jeremiah 38, Jeremiah 39, Jeremiah 40:1-6, 1 Timothy 3, Psalm 119:57-64" ], 292: [ False, "Jeremiah 40:7-16, Jeremiah 41, Jeremiah 42, 1 Timothy 4, Proverbs 25:11-20" ], 293: [ False, "Jeremiah 43, Jeremiah 44, Jeremiah 45, 1 Timothy 5, 1 Timothy 6:1-2, Psalm 119:65-72" ], 294: [ False, "Jeremiah 46, Jeremiah 47, 1 Timothy 6:3-21, Psalm 119:73-80" ], 295: [ False, "Jeremiah 48, Jeremiah 49:1-6, 2 Timothy 1, Psalm 119:81-88" ], 296: [ False, "Jeremiah 49:7-39, Jeremiah 50:1-10, 2 Timothy 2, Proverbs 25:21-28, Proverbs 26:1-2" ], 297: [ False, "Jeremiah 50:11-46, Jeremiah 51:1-14, 2 Timothy 3, Psalm 119:89-96" ], 298: [False, "Jeremiah 51:15-64, 2 Timothy 4, Psalm 119:97-104"], 299: [False, "Jeremiah 52, Titus 1, Psalm 119:105-112"], 300: [ False, "Habakkuk 1, Habakkuk 2, Habakkuk 3:1-19, Titus 2, Proverbs 26:3-12" ], 301: [ False, "Lamentations 1, Lamentations 2:1-6, Titus 3, Psalm 119:113-120" ], 302: [ False, "Lamentations 2:7-27, Lamentations 3:1-39, Philemon 1, Psalm 119:121-128" ], 303: [ False, "Lamentations 3:40-66, Lamentations 4, Lamentations 5, Hebrews 1, Psalm 119:129-136" ], 304: [False, "Obadiah 1, Hebrews 2, Proverbs 26:13-22"], 305: [False, "Joel 1, Joel 2:1-17, Hebrews 3, Psalm 119:137-144"], 306: [ False, "Joel 2:18-32, Joel 3, Hebrews 4:1-13, Psalm 119:145-152" ], 307: [ False, "Ezekiel 1, Ezekiel 2, Ezekiel 3, Hebrews 4:14-16, Hebrews 5:1-10, Psalm 119:153-160" ], 308: [ False, "Ezekiel 4, Ezekiel 5, Ezekiel 6, Hebrews 5:11-14, Hebrews 6:1-12, Proverbs 26:23-28, Proverbs 27:1-4" ], 309: [ False, "Ezekiel 7, Ezekiel 8, Ezekiel 9, Hebrews 6:13-20, Hebrews 7:1-10, Psalm 119:161-168" ], 310: [ False, "Ezekiel 10, Ezekiel 11, Ezekiel 12, Hebrews 7:11-28, Psalm 119:169-176" ], 311: [ False, "Ezekiel 13, Ezekiel 14, Ezekiel 15, Hebrews 8, Psalm 120:1-7" ], 312: [False, "Ezekiel 16, Hebrews 9:1-15, Proverbs 27:5-14"], 313: [False, "Ezekiel 17, Ezekiel 18, Hebrews 9:16-28, Psalm 121:1-8"], 314: [ False, "Ezekiel 19, Ezekiel 20:1-44, Hebrews 10:1-18, Psalm 122:1-9" ], 315: [ False, "Ezekiel 20:45-49, Ezekiel 21, Ezekiel 22:1-22, Hebrews 10:19-39, Psalm 123:1-4" ], 316: [ False, "Ezekiel 22:23-31, Ezekiel 23, Hebrews 11:1-16, Proverbs 27:15-22" ], 317: [ False, "Ezekiel 24, Ezekiel 25, Hebrews 11:17-40, Psalm 124:1-8" ], 318: [False, "Ezekiel 26, Ezekiel 27, Hebrews 12:1-13, Psalm 125:1-5"], 319: [ False, "Ezekiel 28, Ezekiel 29, Hebrews 12:14-29, Psalm 126:1-6" ], 320: [ False, "Ezekiel 30, Ezekiel 31, Hebrews 13, Proverbs 27:23-27, Proverbs 28:1-6" ], 321: [False, "Ezekiel 32, Ezekiel 33:1-32, James 1, Psalm 127:1-5"], 322: [ False, "Ezekiel 33:21-33, Ezekiel 34, Ezekiel 35, James 2, Psalm 128:1-6" ], 323: [False, "Ezekiel 36, Ezekiel 37, James 3, Psalm 129:1-8"], 324: [False, "Ezekiel 38, Ezekiel 39, James 4, Proverbs 28:7-17"], 325: [False, "Ezekiel 40, James 5, Psalm 130:1-8"], 326: [ False, "Ezekiel 41, Ezekiel 42, 1 Peter 1, 1 Peter 2:1-3, Psalm 131:1-3" ], 327: [False, "Ezekiel 43, Ezekiel 44, 1 Peter 2:4-25, Psalm 132:1-18"], 328: [False, "Ezekiel 45, Ezekiel 46, 1 Peter 3, Proverbs 28:18-28"], 329: [False, "Ezekiel 47, Ezekiel 48, 1 Peter 4, Psalm 133:1-3"], 330: [False, "Daniel 1, Daniel 2:1-23, 1 Peter 5, Psalm 134:1-3"], 331: [ False, "Daniel 2:24-49, Daniel 3:1-12, 2 Peter 1, Psalm 135:1-12" ], 332: [ False, "Daniel 3:13-30, Daniel 4:1-18, 2 Peter 2, Proverbs 29:1-9" ], 333: [ False, "Daniel 4:19-37, Daniel 5:1-16, 2 Peter 3, Psalm 135:13-21" ], 334: [ False, "Daniel 5:17-31, Daniel 6:1-28, 1 John 1, 1 John 2, Psalm 136:1-12" ], 335: [ False, "Daniel 7, Daniel 8:1-14, 1 John 2:12-27, Psalm 136:13-26" ], 336: [ False, "Daniel 8:15-27, Daniel 9:1-19, 1 John 2:28-29, 1 John 3:1-10, Proverbs 29:10-18" ], 337: [ False, "Daniel 9:20-27, Daniel 10, Daniel 11:1, 1 John 3:11-24, 1 John 4:1-6, Psalm 137:1-9" ], 338: [False, "Daniel 11:2-35, 1 John 4:7-21, Psalm 138:1-8"], 339: [ False, "Daniel 11:36-45, Daniel 12, 1 John 5:1-21, Psalm 139:1-10" ], 340: [ False, "Haggai 1, Haggai 2:1-23, 2 John 1:1-13, Proverbs 29:19-27" ], 341: [ False, "Zechariah 1, Zechariah 2, Zechariah 3, Zechariah 4, 3 John 1:1-14, Psalm 139:11-16" ], 342: [ False, "Zechariah 5, Zechariah 6, Zechariah 7, Zechariah 8, Jude 1:1-25, Psalm 139:17-24" ], 343: [ False, "Zechariah 9, Zechariah 10, Zechariah 11, Revelation 1, Psalm 140:1-5" ], 344: [ False, "Zechariah 12, Zechariah 13, Zechariah 14, Revelation 2:1-17, Proverbs 30:1-10" ], 345: [ False, "Esther 1, Esther 2:1-18, Revelation 2:18-29, Revelation 3:1-6, Psalm 140:6-13" ], 346: [ False, "Esther 2:19-23, Esther 3, Esther 4, Esther 5, Revelation 3:7-22, Psalm 141:1-10" ], 347: [ False, "Esther 6, Esther 7, Esther 8, Revelation 4, Psalm 142:1-11" ], 348: [False, "Esther 9, Esther 10, Revelation 5, Proverbs 30:11-23"], 349: [ False, "Malachi 1, Malachi 2:1-16, Revelation 6, Psalm 143:1-12" ], 350: [ False, "Malachi 2:17, Malachi 3, Malachi 4, Revelation 7, Psalm 144:1-8" ], 351: [ False, "Ezra 1, Ezra 2:1-67, Revelation 8, Revelation 9:1-12, Psalm 144:9-15" ], 352: [ False, "Ezra 2:68-70, Ezra 3, Ezra 4:1-5, Revelation 9:13-21, Revelation 10, Proverbs 30:24-33" ], 353: [False, "Ezra 4:6-24, Ezra 5, Revelation 11, Psalm 145:1-7"], 354: [ False, "Ezra 6, Ezra 7:1-10, Revelation 12, Revelation 13:1, Psalm 145:8-13" ], 355: [ False, "Ezra 7:11-28, Ezra 8:1-14, Revelation 13:1-18, Psalm 145:13-21" ], 356: [ False, "Ezra 8:15-36, Ezra 9:1-15, Revelation 14:1-13, Proverbs 31:1-9" ], 357: [ False, "Ezra 10, Revelation 14:14-20, Revelation 15, Psalm 146:1-10" ], 358: [False, "Nehemiah 1, Nehemiah 2, Revelation 16, Psalm 147:1-11"], 359: [False, "Nehemiah 3, Nehemiah 4, Revelation 17, Psalm 147:12-20"], 360: [ False, "Nehemiah 5, Nehemiah 6, Nehemiah 7:1-3, Revelation 18:1-17, Proverbs 31:10-20" ], 361: [ False, "Nehemiah 7:4-73, Nehemiah 8, Revelation 18:17-24, Revelation 19:1-10, Psalm 148:1-6" ], 362: [False, "Nehemiah 9:1-37, Revelation 19:11-21, Psalm 148:7-14"], 363: [ False, "Nehemiah 9:38, Nehemiah 10, Nehemiah 11:1-21, Revelation 20, Psalm 149:1-9" ], 364: [ False, "Nehemiah 11:22-36, Nehemiah 12:1-47, Revelation 21, Proverbs 31:21-31" ], 365: [False, "Nehemiah 13, Revelation 22, Psalm 150:1-6"], } translation = ( "Bible Reading Plan", "Today is ", "Search: ", "Open in Tabs", "Hide Checked Items", "Show Checked Items", "Reset All Items", "Save Reading Progress", "Day ", "", "Your reading progress is saved in the following location:", "Failed to save your progress locally. You may need to grant write permission to UBA.", ) def __init__(self, parent): super().__init__() self.parent = parent # set title self.setWindowTitle(self.translation[0]) self.setMinimumSize(830, 500) # set variables self.setupVariables() # setup interface self.setupUI() def setupVariables(self): import copy, os from datetime import date self.today = date.today() self.todayNo = int(format(self.today, '%j')) if self.todayNo > 365: self.todayNo = 365 self.progressFile = os.path.join(os.getcwd(), "plugins", "menu", "{0}.txt".format(self.translation[0])) if os.path.isfile(self.progressFile): from ast import literal_eval with open(self.progressFile, "r") as fileObj: self.plan = literal_eval(fileObj.read()) else: self.plan = copy.deepcopy(self.template) self.hideCheckedItems = False def setupUI(self): from qtpy.QtGui import QStandardItemModel from qtpy.QtWidgets import (QPushButton, QLabel, QListView, QAbstractItemView, QHBoxLayout, QVBoxLayout, QLineEdit) mainLayout = QVBoxLayout() readingListLayout = QVBoxLayout() readingListLayout.addWidget(QLabel(self.translation[0])) readingListLayout.addWidget( QLabel("{0}{1}".format(self.translation[1], self.today))) filterLayout = QHBoxLayout() filterLayout.addWidget(QLabel(self.translation[2])) self.filterEntry = QLineEdit() self.filterEntry.textChanged.connect(self.resetItems) filterLayout.addWidget(self.filterEntry) readingListLayout.addLayout(filterLayout) self.readingList = QListView() self.readingList.setEditTriggers(QAbstractItemView.NoEditTriggers) self.readingListModel = QStandardItemModel(self.readingList) self.readingList.setModel(self.readingListModel) self.resetItems() self.readingListModel.itemChanged.connect(self.itemChanged) #print(self.readingList.currentIndex().row()) #self.readingList.selectionModel().selectionChanged.connect(self.function) readingListLayout.addWidget(self.readingList) buttonsLayout = QHBoxLayout() button = QPushButton(self.translation[3]) button.clicked.connect(self.openInTabs) buttonsLayout.addWidget(button) self.hideShowButton = QPushButton(self.translation[4]) self.hideShowButton.clicked.connect(self.hideShowCheckedItems) buttonsLayout.addWidget(self.hideShowButton) button = QPushButton(self.translation[6]) button.clicked.connect(self.resetAllItems) buttonsLayout.addWidget(button) button = QPushButton(self.translation[7]) button.clicked.connect(self.saveProgress) buttonsLayout.addWidget(button) mainLayout.addLayout(readingListLayout) mainLayout.addLayout(buttonsLayout) self.setLayout(mainLayout) def itemChanged(self, standardItem): from qtpy.QtCore import Qt key = int(standardItem.text().split(".")[0]) if standardItem.checkState() is Qt.CheckState.Checked: self.plan[key][0] = True elif standardItem.checkState() is Qt.CheckState.Unchecked: self.plan[key][0] = False if self.hideCheckedItems: self.resetItems() def resetItems(self): from qtpy.QtGui import QStandardItem from qtpy.QtCore import Qt # Empty the model before reset self.readingListModel.clear() # Reset index = 0 todayIndex = None filterEntry = self.filterEntry.text() for key, value in self.plan.items(): checked, passages = value if not (self.hideCheckedItems and checked) and ( filterEntry == "" or (filterEntry != "" and filterEntry.lower() in passages.lower())): item = QStandardItem("{0}. {1}".format(key, passages)) item.setToolTip("{0}{1}{2}".format(self.translation[8], key, self.translation[9])) if key == self.todayNo: todayIndex = index item.setCheckable(True) item.setCheckState(Qt.CheckState.Checked if checked else Qt. CheckState.Unchecked) self.readingListModel.appendRow(item) index += 1 if todayIndex is not None: self.readingList.setCurrentIndex( self.readingListModel.index(todayIndex, 0)) def hideShowCheckedItems(self): self.hideCheckedItems = not self.hideCheckedItems self.resetItems() self.hideShowButton.setText(self.translation[5] if self. hideCheckedItems else self.translation[4]) def resetAllItems(self): import copy self.plan = copy.deepcopy(self.template) self.resetItems() def translateIntoChinese(self): import copy, pprint from BibleBooks import BibleBooks plan = copy.deepcopy(self.template) filePath = "{0}_zh".format(self.progressFile) with open(filePath, "w", encoding="utf-8") as fileObj: fileObj.write(pprint.pformat(plan)) with open(filePath, "r") as fileObj: text = fileObj.read() translateDict = {} bookNames = [] for key, value in BibleBooks.eng.items(): bookName = value[-1] bookNames.append(bookName) translateDict[bookName] = BibleBooks.sc[key][-1] bookNames = sorted(bookNames, key=len, reverse=True) #print(bookNames) for name in bookNames: text = text.replace(name, translateDict[name]) text = text.replace("Psalm", "诗篇") with open(filePath, "w", encoding="utf-8") as fileObj: fileObj.write(text) def saveProgress(self): import pprint from qtpy.QtWidgets import QMessageBox try: with open(self.progressFile, "w", encoding="utf-8") as fileObj: fileObj.write(pprint.pformat(self.plan)) message = "{0}\n'{1}'".format(self.translation[10], self.progressFile) except: message = self.translation[11] QMessageBox.information(self, self.translation[0], message) def openInTabs(self): dayNo = self.readingList.currentIndex().row() + 1 todayReading = self.plan[dayNo][-1].split(", ") openBibleWindowContentOnNextTab = config.openBibleWindowContentOnNextTab config.openBibleWindowContentOnNextTab = True for reading in todayReading: command = "MAIN:::{0}".format(reading) self.parent.runTextCommand(command) config.openBibleWindowContentOnNextTab = openBibleWindowContentOnNextTab self.close()
class BibleReadingPlan(QWidget): template = { # Source / credits of the following plan: https://www.biblica.com/resources/reading-plans/ 1: [False, '創世記 1, 創世記 2:1-17, 馬太福音 1:1-25, 詩篇 1:1-6'], 2: [False, '創世記 2:18-25, 創世記 3, 創世記 4:1-16, 馬太福音 2:1-18, 詩篇 ' '2:1-12'], 3: [ False, '創世記 4:17-26, 創世記 5, 創世記 6, 馬太福音 2:19-23, 馬太福音 3, 詩篇 ' '3:1-8' ], 4: [False, '創世記 7, 創世記 8, 創世記 9:1-17, 馬太福音 4:1-22, 箴言 1:1-7'], 5: [ False, '創世記 9:18-29, 創世記 10, 創世記 11:1-9, 馬太福音 4:23-25, 馬太福音 ' '5:1-20, 詩篇 4:1-8' ], 6: [False, '創世記 11:10-32, 創世記 12, 創世記 13, 馬太福音 5:21-42, 詩篇 5:1-12'], 7: [False, '創世記 14, 創世記 15, 創世記 16, 馬太福音 5:43-48, 馬太福音 6:1-24, ' '詩篇 6'], 8: [False, '創世記 17, 創世記 18, 馬太福音 6:25-34, 馬太福音 7:1-23, 箴言 ' '1:8-19'], 9: [False, '創世記 19, 創世記 20:1-18, 馬太福音 7:24-29, 馬太福音 8:1-22, 詩篇 ' '7:1-9'], 10: [ False, '創世記 21, 創世記 22, 創世記 23, 馬太福音 8:23-34, 馬太福音 9:1-13, ' '詩篇 7:10-17' ], 11: [False, '創世記 24:1-67, 馬太福音 9:14-38, 詩篇 8:1-9'], 12: [False, '創世記 25, 創世記 26, 馬太福音 10:1-31, 箴言 1:20-33'], 13: [ False, '創世記 27, 創世記 28:1-22, 馬太福音 10:32-42, 馬太福音 11:1-15, 詩篇 ' '9:1-6' ], 14: [False, '創世記 29, 創世記 30, 馬太福音 11:16-30, 詩篇 9:7-12'], 15: [False, '創世記 31:1-55, 馬太福音 12:1-21, 詩篇 9:13-20'], 16: [False, '創世記 32, 創世記 33, 馬太福音 12:22-45, 箴言 2:1-11'], 17: [False, '創世記 34, 創世記 35, 馬太福音 12:46-50, 馬太福音 13:1-17, 詩篇 ' '10:1-11'], 18: [False, '創世記 36, 創世記 37, 馬太福音 13:18-35, 詩篇 10:12-18'], 19: [False, '創世記 38, 創世記 39, 馬太福音 13:36-58, 詩篇 11:1-7'], 20: [False, '創世記 40, 創世記 41:1-40, 馬太福音 14:1-21, 箴言 2:12-22'], 21: [ False, '創世記 41:41-57, 創世記 42, 馬太福音 14:22-36, 馬太福音 15:1-9, 詩篇 ' '12:1-8' ], 22: [False, '創世記 43, 創世記 44, 馬太福音 15:10-39, 詩篇 13:1-6'], 23: [False, '創世記 45, 創世記 46, 創世記 47:1-12, 馬太福音 16:1-20, 詩篇 14:1-7'], 24: [ False, '創世記 47:13-31, 創世記 48, 馬太福音 16:21-28, 馬太福音 17:1-13, ' '箴言 3:1-10' ], 25: [False, '創世記 49, 創世記 50, 馬太福音 17:14-27, 馬太福音 18:1-9, 詩篇 15:1-5'], 26: [False, '約伯記 1, 約伯記 2, 約伯記 3, 馬太福音 18:10-35, 詩篇 16:1-11'], 27: [False, '約伯記 4, 約伯記 5, 約伯記 6, 約伯記 7, 馬太福音 19:1-15, 詩篇 17:1-5'], 28: [False, '約伯記 8, 約伯記 9, 約伯記 10, 馬太福音 19:16-30, 箴言 3:11-20'], 29: [False, '約伯記 11, 約伯記 12, 約伯記 13, 約伯記 14, 馬太福音 20:1-19, 詩篇 17:6-12'], 30: [False, '約伯記 15, 約伯記 16, 約伯記 17, 約伯記 18, 馬太福音 20:20-34, 詩篇 17:13-15'], 31: [False, '約伯記 19, 約伯記 20, 約伯記 21, 馬太福音 21:1-17, 詩篇 18:1-6'], 32: [False, '約伯記 22, 約伯記 23, 約伯記 24, 馬太福音 21:18-32, 箴言 3:21-35'], 33: [ False, '約伯記 25, 約伯記 26, 約伯記 27, 約伯記 28, 約伯記 29, 馬太福音 21:33-46, 馬太福音 ' '22:1-14, 詩篇 18:7-15' ], 34: [False, '約伯記 30, 約伯記 31, 約伯記 32, 馬太福音 22:15-46, 詩篇 18:16-24'], 35: [False, '約伯記 33, 約伯記 34, 馬太福音 23:1-39, 詩篇 18:25-36'], 36: [False, '約伯記 35, 約伯記 36, 約伯記 37, 馬太福音 24:1-31, 箴言 4:1-9'], 37: [ False, '約伯記 38, 約伯記 39, 約伯記 40:1-2, 馬太福音 24:32-51, 馬太福音 25:1-13, 詩篇 ' '18:37-42' ], 38: [False, '約伯記 40:3-24, 約伯記 41, 約伯記 42, 馬太福音 25:14-46, 詩篇 18:43-50'], 39: [False, '出埃及記 1, 出埃及記 2, 出埃及記 3, 馬太福音 26:1-30, 詩篇 19:1-6'], 40: [False, '出埃及記 4, 出埃及記 5, 出埃及記 6:1-12, 馬太福音 26:31-46, 箴言 4:10-19'], 41: [False, '出埃及記 6:13-30, 出埃及記 7,出埃及記 8, 馬太福音 26:47-68, 詩篇 19:7-14'], 42: [False, '出埃及記 9, 出埃及記 10, 馬太福音 26:69-75, 馬太福音 27:1-10, 詩篇 20:1-9'], 43: [False, '出埃及記 11, 出埃及記 12, 馬太福音 27:11-44, 詩篇 21:1-7'], 44: [False, '出埃及記 13, 出埃及記 14, 馬太福音 27:45-66, 箴言 4:20-27'], 45: [False, '出埃及記 15, 出埃及記 16, 馬太福音 28:1-20, 詩篇 21:8-13'], 46: [False, '出埃及記 17, 出埃及記 18, 馬可福音 1:1-28, 詩篇 22:1-11'], 47: [False, '出埃及記 19, 出埃及記 20, 馬可福音 1:29-45, 馬可福音 2:1-17, 詩篇 22:12-21'], 48: [False, '出埃及記 21, 出埃及記 22, 馬可福音 2:18-27, 馬可福音 3:1-30, 箴言 5:1-14'], 49: [False, '出埃及記 23, 出埃及記 24, 馬可福音 3:31-35, 馬可福音 4:1-29, 詩篇 22:22-31'], 50: [False, '出埃及記 25, 出埃及記 26, 馬可福音 4:30-41, 馬可福音 5:1-20, 詩篇 23:1-6'], 51: [False, '出埃及記 27, 出埃及記 28, 馬可福音 5:21-43, 馬可福音 6:1-6, 詩篇 24:1-10'], 52: [False, '出埃及記 29, 出埃及記 30, 馬可福音 6:7-29, 箴言 5:15-23'], 53: [False, '出埃及記 31, 出埃及記 32, 出埃及記 33:1-6, 馬可福音 6:30-56, 詩篇 25:1-7'], 54: [False, '出埃及記 33:7-23, 出埃及記 34, 馬可福音 7:1-30, 詩篇 25:8-15'], 55: [False, '出埃及記 35, 出埃及記 36, 馬可福音 7:31-37, 馬可福音 8:1-13, 詩篇 25:16-22'], 56: [False, '出埃及記 37, 出埃及記 38, 馬可福音 8:14-38, 馬可福音 9:1, 箴言 6:1-11'], 57: [False, '出埃及記 39, 出埃及記 40, 馬可福音 9:2-32, 詩篇 26:1-12'], 58: [ False, '利未記 1, 利未記 2, 利未記 3, 馬可福音 9:33-50, 馬可福音 10:1-12, ' '詩篇 27:1-6' ], 59: [False, '利未記 4, 利未記 5:1-13, 馬可福音 10:13-31, 詩篇 27:7-14'], 60: [ False, '利未記 5:14-19, 利未記 6, 利未記 7:1-10, 馬可福音 10:32-52, ' '箴言 6:12-19' ], 61: [False, '利未記 7:11-38, 利未記 8, 馬可福音 11:1-27, 詩篇 28'], 62: [False, '利未記 9, 利未記 10, 馬可福音 11:28-33, 馬可福音 12:1-12, 詩篇 29'], 63: [False, '利未記 11, 利未記 12, 馬可福音 12:13-27, 詩篇 30:1-7'], 64: [False, '利未記 13:1-59, 馬可福音 12:28-44, 箴言 6:20-29'], 65: [False, '利未記 14:1-57, 馬可福音 13:1-31, 詩篇 30:8-12'], 66: [False, '利未記 15, 利未記 16, 馬可福音 13:32-37, 馬可福音 14:1-16, 詩篇 31:1-8'], 67: [False, '利未記 17, 利未記 18, 馬可福音 14:17-42, 詩篇 31:9-18'], 68: [False, '利未記 19, 利未記 20, 馬可福音 14:43-72, 箴言 6:30-35'], 69: [False, '利未記 21, 利未記 22, 馬可福音 15:1-32, 詩篇 31:19-24'], 70: [False, '利未記 23, 利未記 24, 馬可福音 15:33-47, 詩篇 32'], 71: [False, '利未記 25, 利未記 26:1-13, 馬可福音 16:1-20, 詩篇 33:1-11'], 72: [False, '利未記 26:14-46, 利未記 27, 路加福音 1:1-25, 箴言 7:1-5'], 73: [False, '民數記 1, 民數記 2:1-9, 路加福音 1:26-38, 詩篇 33:12-22'], 74: [False, '民數記 2:10-34, 民數記 3, 路加福音 1:39-56, 詩篇 34:1-10'], 75: [False, '民數記 4, 民數記 5:1-10, 路加福音 1:57-80, 詩篇 34:11-22'], 76: [False, '民數記 5:11-31, 民數記 6:1-27, 路加福音 2:1-20, 箴言 7:6-20'], 77: [False, '民數記 7:1-65, 路加福音 2:21-40, 詩篇 35:1-10'], 78: [ False, '民數記 7:66-89, 民數記 8, 民數記 9:1-14, 路加福音 2:41-52, 詩篇 ' '35:11-18' ], 79: [ False, '民數記 9:15-23, 民數記 10, 民數記 11:1-3, 路加福音 3:1-22, 詩篇 ' '35:19-28' ], 80: [ False, '民數記 11:4-35, 民數記 12, 民數記 13:1-25, 路加福音 3:23-38, 路加福音 ' '4:1-13, 箴言 7:21-27' ], 81: [False, '民數記 13:26-33, 民數記 14, 路加福音 4:14-37, 詩篇 36:1-12'], 82: [False, '民數記 15, 民數記 16:1-35, 路加福音 4:38-44, 路加福音 5:1-16, 詩篇 37:1-9'], 83: [False, '民數記 16:36-50, 民數記 17, 民數記 18, 路加福音 5:17-32, 詩篇 37:10-20'], 84: [ False, '民數記 19, 民數記 20, 民數記 21:1-3, 路加福音 5:33-39, 路加福音 6:1-11, ' '箴言 8:1-11' ], 85: [False, '民數記 21:4-35, 民數記 22:1-20, 路加福音 6:12-36, 詩篇 37:21-31'], 86: [ False, '民數記 22:21-41, 民數記 23:1-26, 路加福音 6:37-49, 路加福音 7:1-10, 詩篇 ' '37:32-40' ], 87: [False, '民數記 23:27-30, 民數記 24, 民數記 25, 路加福音 7:11-35, 詩篇 38:1-11'], 88: [False, '民數記 26, 民數記 27:1-11, 路加福音 7:36-50, 箴言 8:12-21'], 89: [ False, '民數記 27:12-23, 民數記 28, 民數記 29:1-11, 路加福音 8:1-18, 詩篇 ' '38:12-22' ], 90: [ False, '民數記 29:12-40, 民數記 30, 民數記 31:1-24, 路加福音 8:19-39, 詩篇 ' '39:1-13' ], 91: [False, '民數記 31:25-54, 民數記 32, 路加福音 8:40-56, 路加福音 9:1-9, 詩篇 40:1-8'], 92: [False, '民數記 33, 民數記 34, 路加福音 9:10-27, 箴言 8:22-31'], 93: [False, '民數記 35, 民數記 36:1-12, 路加福音 9:28-56, 詩篇 40:9-17'], 94: [False, '申命記 1, 申命記 2:1-23, 路加福音 9:57-62, 路加福音 10:1-24, 詩篇 ' '41:1-6'], 95: [ False, '申命記 2:24-37, 申命記 3, 申命記 4:1-14, 路加福音 10:25-42, ' '路加福音 11:1-4, 詩篇 41:7-13' ], 96: [False, '申命記 4:15-49, 申命記 5, 路加福音 11:5-32, 箴言 8:32-36'], 97: [False, '申命記 6, 申命記 7, 申命記 8, 路加福音 11:33-54, 詩篇 ' '42:1-6'], 98: [False, '申命記 9, 申命記 10, 路加福音 12:1-34, 詩篇 42:7-11'], 99: [False, '申命記 11, 申命記 12, 路加福音 12:35-59, 詩篇 43:1-5'], 100: [False, '申命記 13, 申命記 14, 路加福音 13:1-30, 箴言 9:1-12'], 101: [ False, '申命記 15, 申命記 16:1-20, 路加福音 13:31-35, 路加福音 14:1-14, ' '詩篇 44:1-12' ], 102: [ False, '申命記 16:21-22, 申命記 17, 申命記 18, 路加福音 14:15-35, ' '詩篇 44:13-26' ], 103: [False, '申命記 19, 申命記 20, 路加福音 15:1-32, 詩篇 45:1-9'], 104: [False, '申命記 21, 申命記 22, 路加福音 16:1-18, 箴言 9:13-18'], 105: [ False, '申命記 23, 申命記 24, 申命記 25:1-19, 路加福音 16:19-31, ' '路加福音 17:1-10, 詩篇 45:10-17' ], 106: [ False, '申命記 26, 申命記 27, 申命記 28:1-14, 路加福音 17:11-37, ' '詩篇 46:1-11' ], 107: [False, '申命記 28:15-68, 路加福音 18:1-30, 詩篇 47:1-9'], 108: [ False, '申命記 29, 申命記 30:1-10, 路加福音 18:31-43, 路加福音 19:1-10, ' '箴言 10:1-10' ], 109: [False, '申命記 30:11-20, 申命記 31:1-29, 路加福音 19:11-44, 詩篇 ' '48:1-8'], 110: [ False, '申命記 31:30, 申命記 32, 路加福音 19:45-48, 路加福音 20:1-26, 詩篇 ' '48:9-14' ], 111: [ False, '申命記 33, 申命記 34:1-12, 路加福音 20:27-47, 路加福音 21:1-4, 詩篇 ' '49:1-20' ], 112: [False, '約書亞記 1, 約書亞記 2, 路加福音 21:5-38, 箴言 10:11-20'], 113: [False, '約書亞記 3, 約書亞記 4, 約書亞記 5:1-12, 路加福音 22:1-38, 詩篇 50:1-15'], 114: [ False, '約書亞記 5:13-15, 約書亞記 6, 約書亞記 7, 路加福音 22:39-62, 詩篇 50:16-23' ], 115: [False, '約書亞記 8, 約書亞記 9:1-15, 路加福音 22:63-71, 路加福音 23:1-25, 詩篇 51:1-9'], 116: [False, '約書亞記 9:16-27, 約書亞記 10, 路加福音 23:26-56, 箴言 10:21-30'], 117: [False, '約書亞記 11, 約書亞記 12, 路加福音 24:1-35, 詩篇 51:10-19'], 118: [False, '約書亞記 13, 約書亞記 14, 路加福音 24:36-53, 詩篇 52:1-9'], 119: [False, '約書亞記 15, 約書亞記 16, 約翰福音 1:1-28, 詩篇 53:1-6'], 120: [ False, '約書亞記 17, 約書亞記 18, 約翰福音 1:29-51, 箴言 10:31-32, 箴言 ' '11:1-8' ], 121: [False, '約書亞記 19, 約書亞記 20, 約書亞記 21:1-19, 約翰福音 2:1-25, 詩篇 54:1-7'], 122: [False, '約書亞記 21:20-45, 約書亞記 22, 約翰福音 3:1-21, 詩篇 55:1-11'], 123: [False, '約書亞記 23, 約書亞記 24, 約翰福音 3:22-36, 詩篇 55:12-23'], 124: [False, '士師記 1, 士師記 2:1-5, 約翰福音 4:1-26, 箴言 11:9-18'], 125: [False, '士師記 2:6-23, 士師記 3, 約翰福音 4:27-42, 詩篇 56:1-13'], 126: [False, '士師記 4, 士師記 5, 約翰福音 4:43-54, 約翰福音 5:1-15, 詩篇 57:1-6'], 127: [False, '士師記 6, 士師記 7:1-8, 約翰福音 5:16-30, 詩篇 57:7-11'], 128: [False, '士師記 7:8-25, 士師記 8, 約翰福音 5:31-47, 箴言 11:19-28'], 129: [False, '士師記 9, 約翰福音 6:1-24, 詩篇 58:1-11'], 130: [False, '士師記 10, 士師記 11, 約翰福音 6:25-59, 詩篇 59:1-8'], 131: [False, '士師記 12, 士師記 13, 約翰福音 6:60-71, 約翰福音 7:1-13, 詩篇 59:9-19'], 132: [ False, '士師記 14, 士師記 15, 約翰福音 7:14-44, 箴言 11:29-31, 箴言 ' '12:1-7' ], 133: [False, '士師記 16, 士師記 17, 約翰福音 7:45-53, 約翰福音 8:1-11, 詩篇 60:1-4'], 134: [False, '士師記 18, 士師記 19, 約翰福音 8:12-30, 詩篇 60:5-12'], 135: [False, '士師記 20, 士師記 21, 約翰福音 8:31-59, 詩篇 61:1-8'], 136: [False, '路得記 1, 路得記 2, 約翰福音 9:1-34, 箴言 12:8-17'], 137: [False, '路得記 3, 路得記 4, 約翰福音 9:35-41, 約翰福音 10:1-21, 詩篇 62:1-12'], 138: [False, '撒母耳記上 1, 撒母耳記上 2:1-26, 約翰福音 10:22-42, 詩篇 63:1-11'], 139: [ False, '撒母耳記上 2:27-36, 撒母耳記上 3, 撒母耳記上 4, 約翰福音 11:1-44, 詩篇 64:1-10' ], 140: [ False, '撒母耳記上 5, 撒母耳記上 6, 撒母耳記上 7, 約翰福音 11:45-57, 約翰福音 12:1-11, ' '箴言 12:18-27' ], 141: [ False, '撒母耳記上 8, 撒母耳記上 9, 撒母耳記上 10:1-8, 約翰福音 12:12-26, 詩篇 65:1-13' ], 142: [ False, '撒母耳記上 10:9-27, 撒母耳記上 11, 撒母耳記上 12, 約翰福音 12:37-50, 約翰福音 ' '13:1-17, 詩篇 66:1-12' ], 143: [False, '撒母耳記上 13, 撒母耳記上 14:1-23, 約翰福音 13:18-38, 詩篇 66:13-20'], 144: [ False, '撒母耳記上 14:24-52, 撒母耳記上 15, 約翰福音 14:1-31, 箴言 12:28, 箴言 ' '13:1-9' ], 145: [ False, '撒母耳記上 16, 撒母耳記上 17:1-37, 約翰福音 15, 約翰福音 16:1-4, 詩篇 67:1-7' ], 146: [ False, '撒母耳記上 17:38-58, 撒母耳記上 18, 約翰福音 16:5-33, 約翰福音 17:1-5, 詩篇 ' '68:1-6' ], 147: [False, '撒母耳記上 19, 撒母耳記上 20, 約翰福音 17:6-26, 詩篇 68:7-14'], 148: [ False, '撒母耳記上 21, 撒母耳記上 22, 撒母耳記上 23, 約翰福音 18:1-24, 箴言 ' '13:10-19' ], 149: [False, '撒母耳記上 24, 撒母耳記上 25, 約翰福音 18:25-40, 詩篇 68:15-20'], 150: [ False, '撒母耳記上 26, 撒母耳記上 27, 撒母耳記上 28, 約翰福音 19:1-27, 詩篇 68:21-27' ], 151: [ False, '撒母耳記上 29, 撒母耳記上 30, 撒母耳記上 31, 約翰福音 19:28-42, 約翰福音 20:1-9, ' '詩篇 68:28-35' ], 152: [ False, '撒母耳記下 1, 撒母耳記下 2:1-7, 約翰福音 20:10-31, 箴言 13:20-25, 箴言 ' '14:1-4' ], 153: [False, '撒母耳記下 2:8-32, 撒母耳記下 3:1-21, 約翰福音 21:1-25, 詩篇 69:1-12'], 154: [ False, '撒母耳記下 3:22-39, 撒母耳記下 4, 撒母耳記下 5:1-5, 使徒行傳 1:1-22, 詩篇 ' '69:13-28' ], 155: [ False, '撒母耳記下 5:6-25, 撒母耳記下 6, 使徒行傳 1:23-26, 使徒行傳 2:1-21, 詩篇 ' '69:29-36' ], 156: [False, '撒母耳記下 7, 撒母耳記下 8, 使徒行傳 2:22-47, 箴言 14:4-14'], 157: [False, '撒母耳記下 9, 撒母耳記下 10, 使徒行傳 3, 詩篇 70:1-5'], 158: [False, '撒母耳記下 11, 撒母耳記下 12, 使徒行傳 4:1-22, 詩篇 71:1-8'], 159: [False, '撒母耳記下 13, 使徒行傳 4:23-37, 使徒行傳 5:1-11, 詩篇 71:9-18'], 160: [False, '撒母耳記下 14, 撒母耳記下 15:1-12, 使徒行傳 5:12-42, 箴言 14:15-24'], 161: [ False, '撒母耳記下 15:13-37, 撒母耳記下 16:1-14, 使徒行傳 6, 使徒行傳 7:1-19, 詩篇 ' '71:19-24' ], 162: [ False, '撒母耳記下 16:15-23, 撒母耳記下 17, 撒母耳記下 18:1-18, 使徒行傳 7:20-43, 詩篇 ' '72:1-20' ], 163: [ False, '撒母耳記下 18:19-33, 撒母耳記下 19, 使徒行傳 7:44-60, 使徒行傳 8:1-3, 詩篇 ' '73:1-14' ], 164: [False, '撒母耳記下 20, 撒母耳記下 21, 使徒行傳 8:4-40, 箴言 14:25-35'], 165: [False, '撒母耳記下 22, 撒母耳記下 23:1-7, 使徒行傳 9:1-31, 詩篇 73:15-28'], 166: [ False, '撒母耳記下 23:8-39, 撒母耳記下 24:1-25, 使徒行傳 9:32-43, 使徒行傳 10:1-23, 詩篇 ' '74:1-9' ], 167: [ False, '列王紀上 1, 列王紀上 2:1-12, 使徒行傳 10:23-48, 使徒行傳 11:1-18, 詩篇 ' '74:10-17' ], 168: [ False, '列王紀上 2:13-46, 列王紀上 3:1-15, 使徒行傳 11:19-30, 使徒行傳 12:1-19, 箴言 ' '15:1-10' ], 169: [ False, '列王紀上 3:16-28, 列王紀上 4, 列王紀上 5, 使徒行傳 12:19-25, 使徒行傳 13:1-12, ' '詩篇 74:18-23' ], 170: [False, '列王紀上 6, 列王紀上 7:1-22, 使徒行傳 13:13-41, 詩篇 75:1-10'], 171: [ False, '列王紀上 7:23-51, 列王紀上 8:1-21, 使徒行傳 13:42-52, 使徒行傳 14:1-7, 詩篇 ' '76:1-12' ], 172: [False, '列王紀上 8:22-66, 列王紀上 9:1-9, 使徒行傳 14:8-28, 箴言 15:11-20'], 173: [ False, '列王紀上 9:10-28, 列王紀上 10, 列王紀上 11:1-13, 使徒行傳 15:1-21, 詩篇 ' '77:1-9' ], 174: [ False, '列王紀上 11:14-43, 列王紀上 12:1-24, 使徒行傳 15:22-41, 詩篇 77:10-20' ], 175: [ False, '列王紀上 12:25-33, 列王紀上 13, 列王紀上 14:1-20, 使徒行傳 16:1-15, 詩篇 ' '78:1-8' ], 176: [ False, '列王紀上 14:21-31, 列王紀上 15, 列王紀上 16:1-7, 使徒行傳 16:16-40, 箴言 ' '15:21-30' ], 177: [ False, '列王紀上 16:8-34, 列王紀上 17, 列王紀上 18:1-15, 使徒行傳 17:1-21, 詩篇 ' '78:9-16' ], 178: [ False, '列王紀上 18:16-46, 列王紀上 19, 使徒行傳 17:22-34, 使徒行傳 18:1-8, 詩篇 ' '78:17-31' ], 179: [ False, '列王紀上 20, 列王紀上 21, 使徒行傳 18:9-28, 使徒行傳 19:1-13, 詩篇 78:32-39' ], 180: [False, '列王紀上 22:1-53, 使徒行傳 19:14-41, 箴言 15:31-33, 箴言 16:1-7'], 181: [False, '列王紀下 1, 列王紀下 2:1-25, 使徒行傳 20:1-38, 詩篇 78:40-55'], 182: [False, '列王紀下 3, 列王紀下 4:1-37, 使徒行傳 21:1-26, 詩篇 78:56-72'], 183: [ False, '列王紀下 4:38-44, 列王紀下 5, 列王紀下 6:1-23, 使徒行傳 21:27-40, 使徒行傳 ' '22:1-22, 詩篇 79:1-13' ], 184: [ False, '列王紀下 6:24-33, 列王紀下 7, 列王紀下 8:1-15, 使徒行傳 22:22-30, 使徒行傳 ' '23:1-11, 箴言 16:8-17' ], 185: [False, '列王紀下 8:16-29, 列王紀下 9, 使徒行傳 23:12-35, 詩篇 80:1-7'], 186: [False, '列王紀下 10, 列王紀下 11, 使徒行傳 24:1-27, 詩篇 80:8-19'], 187: [ False, '列王紀下 12, 列王紀下 13, 列王紀下 14:1-22, 使徒行傳 25:1-22, 詩篇 81:1-7' ], 188: [ False, '列王紀下 14:23-29, 列王紀下 15, 使徒行傳 25:23-27, 使徒行傳 26:1-23, 箴言 ' '16:18-27' ], 189: [ False, '列王紀下 16, 列王紀下 17, 使徒行傳 26:24-32, 使徒行傳 27:1-12, 詩篇 81:8-16' ], 190: [False, '列王紀下 18, 列王紀下 19:1-13, 使徒行傳 27:13-44, 詩篇 82:1-8'], 191: [False, '列王紀下 19:14-37, 列王紀下 20, 使徒行傳 28:1-16, 詩篇 83:1-18'], 192: [ False, '列王紀下 21, 列王紀下 22, 使徒行傳 28:17-31, 箴言 16:28-33, 箴言 ' '17:1-4' ], 193: [False, '列王紀下 23, 列王紀下 24:1-7, 羅馬書 1:1-17, 詩篇 84:1-7'], 194: [False, '列王紀下 24:8-20, 列王紀下 25, 羅馬書 1:18-32, 詩篇 84:8-12'], 195: [False, '約拿書 1, 約拿書 2, 約拿書 3, 約拿書 4, 羅馬書 2:1-16, 詩篇 85:1-7'], 196: [False, '阿摩司書 1, 阿摩司書 2, 羅馬書 2:17-29, 羅馬書 3:1-8, 箴言 17:5-14'], 197: [False, '阿摩司書 3, 阿摩司書 4, 羅馬書 3:9-31, 詩篇 85:8-13'], 198: [False, '阿摩司書 5, 羅馬書 4:1-15, 詩篇 86:1-10'], 199: [False, '阿摩司書 6, 阿摩司書 7, 羅馬書 4:16-25, 羅馬書 5:1-11, 詩篇 86:11-17'], 200: [False, '阿摩司書 8, 阿摩司書 9, 羅馬書 5:12-21, 箴言 17:15-24'], 201: [False, '何西阿書 1, 何西阿書 2, 羅馬書 6:1-14, 詩篇 87:1-7'], 202: [ False, '何西阿書 3, 何西阿書 4, 何西阿書 5, 羅馬書 6:15-23, 羅馬書 7:1-6, 詩篇 88:1-9' ], 203: [False, '何西阿書 6, 何西阿書 7, 羅馬書 7:7-25, 詩篇 88:9-18'], 204: [False, '何西阿書 8, 何西阿書 9, 羅馬書 8:1-17, 箴言 17:25-28, 箴言 18:1-6'], 205: [False, '何西阿書 10, 何西阿書 11, 羅馬書 8:18-39, 詩篇 89:1-8'], 206: [ False, '何西阿書 11, 何西阿書 12, 何西阿書 13, 何西阿書 14, 羅馬書 9:1-21, 詩篇 89:9-13' ], 207: [ False, '歷代志上 1, 歷代志上 2:1-17, 羅馬書 9:22-33, 羅馬書 10:1-4, ' '詩篇 89:14-18' ], 208: [ False, '歷代志上 2:18-55, 歷代志上 3, 歷代志上 4:1-8, 羅馬書 ' '10:5-21, 羅馬書 11:1-10, 箴言 18:7-16' ], 209: [False, '歷代志上 4:9-43, 歷代志上 5, 羅馬書 11:11-32, 詩篇 89:19-29'], 210: [False, '歷代志上 6, 羅馬書 11:33-36, 羅馬書 12:1-21, 詩篇 89:30-37'], 211: [False, '歷代志上 7, 歷代志上 8, 羅馬書 13:1-14, 詩篇 89:38-45'], 212: [ False, '歷代志上 9, 歷代志上 10:1-14, 羅馬書 14:1-18, 箴言 ' '18:17-24, 箴言 19:1-2' ], 213: [ False, '歷代志上 11, 歷代志上 12:1-22, 羅馬書 14:19-23, 羅馬書 ' '15:1-13, 詩篇 89:46-52' ], 214: [ False, '歷代志上 12:23-40, 歷代志上 13, 歷代志上 14, 羅馬書 ' '15:14-33, 詩篇 90:1-10' ], 215: [False, '歷代志上 15, 歷代志上 16:1-36, 羅馬書 16, 詩篇 90:11-17'], 216: [ False, '歷代志上 16:37-43, 歷代志上 17, 歷代志上 18, 哥林多前書 ' '1:1-17, 箴言 19:3-12' ], 217: [ False, '歷代志上 19, 歷代志上 20, 歷代志上 21, 哥林多前書 ' '1:18-31, 哥林多前書 2:1-5, 詩篇 91:1-8' ], 218: [False, '歷代志上 22, 歷代志上 23, 哥林多前書 2:6-16, 詩篇 91:9-16'], 219: [False, '歷代志上 24, 歷代志上 25, 歷代志上 26:1-19, 哥林多前書 ' '3, 詩篇 92:1-15'], 220: [False, '歷代志上 26:20-32, 歷代志上 27, 哥林多前書 4, 箴言 ' '19:13-22'], 221: [False, '歷代志上 28, 歷代志上 29, 哥林多前書 5, 詩篇 93:1-5'], 222: [False, '歷代志下 1:1-17, 哥林多前書 6, 詩篇 94:1-11'], 223: [False, '傳道書 1, 傳道書 2, 傳道書 3:1-22, 哥林多前書 ' '7:1-16, 詩篇 94:12-23'], 224: [ False, '傳道書 4, 傳道書 5, 傳道書 6, 哥林多前書 7:17-35, ' '箴言 19:23-29, 箴言 20:1-4' ], 225: [ False, '傳道書 7, 傳道書 8, 傳道書 9:1-12, 哥林多前書 ' '7:36-40, 哥林多前書 8:1-13, 詩篇 95:1-11' ], 226: [ False, '傳道書 9:13-18, 傳道書 10, 傳道書 11, 傳道書 ' '12, 哥林多前書 9:1-18, 詩篇 96:1-13' ], 227: [ False, '歷代志下 2, 歷代志下 3, 歷代志下 4, 歷代志下 5:1, 哥林多前書 9:19-27, 哥林多前書 10:1-13, 詩篇 97:1-12' ], 228: [ False, '歷代志下 5:2-14, 歷代志下 6, 歷代志下 7:1-10, 哥林多前書 10:14-33, 哥林多前書 11:1, 箴言 20:5-14' ], 229: [ False, '歷代志下 7:11-22, 歷代志下 8, 歷代志下 9, 哥林多前書 ' '11:2-34, 詩篇 98:1-9' ], 230: [False, '雅歌 1, 雅歌 2, 雅歌 3, 雅歌 4, 哥林多前書 12:1-26, 詩篇 99:1-9'], 231: [ False, '雅歌 5, 雅歌 6, 雅歌 7, 雅歌 8, 哥林多前書 12:27-31, 哥林多前書 ' '13:1-13, 詩篇 100:1-5' ], 232: [ False, '歷代志下 10, 歷代志下 11, 歷代志下 12, 哥林多前書 ' '14:1-19, 箴言 20:15-24' ], 233: [ False, '歷代志下 13, 歷代志下 14, 歷代志下 15, 哥林多前書 ' '14:20-40, 詩篇 101:1-8' ], 234: [ False, '歷代志下 16, 歷代志下 17, 歷代志下 18:1-27, 哥林多前書 ' '15:1-34, 詩篇 102:1-11' ], 235: [ False, '歷代志下 18:28-34, 歷代志下 19, 歷代志下 20, 哥林多前書 ' '15:35-49, 詩篇 102:12-17' ], 236: [ False, '歷代志下 21, 歷代志下 22, 歷代志下 23, 哥林多前書 ' '15:50-58, 哥林多前書 16:1-4, 箴言 20:25-30, 箴言 21:1-4' ], 237: [False, '歷代志下 24, 歷代志下 25, 哥林多前書 16:5-24, 詩篇 ' '102:18-28'], 238: [ False, '歷代志下 26, 歷代志下 27, 歷代志下 28, 哥林多後書 ' '1:1-11, 詩篇 103:1-12' ], 239: [ False, '歷代志下 29, 歷代志下 30, 歷代志下 31:1, 哥林多後書 ' '1:12-22, 詩篇 103:13-22' ], 240: [ False, '歷代志下 31:2-21, 歷代志下 32, 歷代志下 33:1-20, 哥林多後書 1:23, 哥林多後書 2:1-11, 箴言 21:5-16' ], 241: [ False, '歷代志下 33:21-24, 歷代志下 34, 歷代志下 35:1-19, 哥林多後書 2:12-17, 哥林多後書 3:1-6, 詩篇 104:1-18' ], 242: [False, '歷代志下 35:20-27, 歷代志下 36, 哥林多後書 3:7-18, 詩篇 ' '104:19-30'], 243: [False, '彌迦書 1, 彌迦書 2, 彌迦書 3, 彌迦書 4, 哥林多後書 4, 詩篇 104:31-35'], 244: [False, '彌迦書 5, 彌迦書 6, 彌迦書 7, 哥林多後書 5:1-10, 箴言 21:17-26'], 245: [ False, '以賽亞書 1, 以賽亞書 2, 哥林多後書 5:11-21, 哥林多後書 6:1-2, 詩篇 ' '105:1-11' ], 246: [ False, '以賽亞書 3, 以賽亞書 4, 以賽亞書 5:1-7, 哥林多後書 6:3-18, 哥林多後書 ' '7:1, 詩篇 105:12-22' ], 247: [ False, '以賽亞書 5:8-30, 以賽亞書 6, 以賽亞書 7, 以賽亞書 8:1-10, 哥林多後書 ' '7:2-16, 詩篇 105:23-36' ], 248: [ False, '以賽亞書 8:11-22, 以賽亞書 9, 以賽亞書 10:1-19, 哥林多後書 8:1-15, ' '箴言 21:27-31, 箴言 22:1-6' ], 249: [ False, '以賽亞書 10:20-34, 以賽亞書 11, 以賽亞書 12, 以賽亞書 13, 哥林多後書 ' '8:16-24, 哥林多後書 9:1-5, 詩篇 105:37-45' ], 250: [False, '以賽亞書 14, 以賽亞書 15, 以賽亞書 16, 哥林多後書 9:6-15, 詩篇 106:1-15'], 251: [False, '以賽亞書 17, 以賽亞書 18, 以賽亞書 19, 哥林多後書 10, 詩篇 106:16-31'], 252: [ False, '以賽亞書 20, 以賽亞書 21, 以賽亞書 22, 以賽亞書 23, 哥林多後書 11:1-15, ' '箴言 22:7-16' ], 253: [ False, '以賽亞書 24, 以賽亞書 25, 以賽亞書 26, 哥林多後書 11:16-33, 詩篇 ' '106:32-39' ], 254: [False, '以賽亞書 27, 以賽亞書 28, 哥林多後書 12:1-10, 詩篇 106:40-48'], 255: [False, '以賽亞書 29, 以賽亞書 30:1-18, 哥林多後書 12:11-21, 詩篇 107:1-9'], 256: [ False, '以賽亞書 30:19-33, 以賽亞書 31, 以賽亞書 32, 哥林多後書 13, 箴言 ' '22:17-27' ], 257: [False, '以賽亞書 33, 以賽亞書 34, 以賽亞書 35, 加拉太書 1, 詩篇 107:10-22'], 258: [False, '以賽亞書 36, 以賽亞書 37, 加拉太書 2:1-10, 詩篇 107:23-32'], 259: [ False, '以賽亞書 38, 以賽亞書 39, 以賽亞書 40, 加拉太書 2:11-21, 加拉太書 3:1-9, ' '詩篇 107:33-43' ], 260: [ False, '以賽亞書 41, 以賽亞書 42, 加拉太書 3:10-25, 箴言 22:28-29, 箴言 ' '23:1-9' ], 261: [ False, '以賽亞書 43, 以賽亞書 44:1-23, 加拉太書 3:26-29, 加拉太書 4:1-20, 詩篇 ' '108:1-5' ], 262: [ False, '以賽亞書 44:24-28, 以賽亞書 45, 以賽亞書 46, 加拉太書 4:21-31, 加拉太書 ' '5:1-6, 詩篇 108:6-13' ], 263: [ False, '以賽亞書 47, 以賽亞書 48, 以賽亞書 49:1-7, 加拉太書 5:7-26, 詩篇 109:1-20' ], 264: [ False, '以賽亞書 49:8-26, 以賽亞書 50, 以賽亞書 51:1-16, 加拉太書 6, 箴言 ' '23:10-18' ], 265: [ False, '以賽亞書 51:17-23, 以賽亞書 52, 以賽亞書 53, 以賽亞書 54, 以弗所書 1, 詩篇 ' '109:21-31' ], 266: [False, '以賽亞書 55, 以賽亞書 56, 以賽亞書 57:1-13, 以弗所書 2, 詩篇 110:1-7'], 267: [False, '以賽亞書 57:14-21, 以賽亞書 58, 以賽亞書 59, 以弗所書 3, 詩篇 111:1-10'], 268: [False, '以賽亞書 60, 以賽亞書 61, 以賽亞書 62, 以弗所書 4:1-16, 箴言 23:19-28'], 269: [ False, '以賽亞書 63, 以賽亞書 64, 以賽亞書 65:1-16, 以弗所書 4:17-32, 以弗所書 ' '5:1-7, 詩篇 112:1-10' ], 270: [False, '以賽亞書 65:17-25, 以賽亞書 66, 以弗所書 5:8-33, 詩篇 113:1-9'], 271: [False, '那鴻書 1, 那鴻書 2, 那鴻書 3, 以弗所書 6, 詩篇 114:1-8'], 272: [ False, '西番雅書 1, 西番雅書 2, 西番雅書 3, 腓立比書 1:1-26, 箴言 ' '23:29-35, 箴言 24:1-4' ], 273: [ False, '耶利米書 1, 耶利米書 2:1-30, 腓立比書 1:27-30, 腓立比書 2:1-11, ' '詩篇 115:1-11' ], 274: [ False, '耶利米書 2:31-47, 耶利米書 3, 耶利米書 4:1-9, 腓立比書 2:12-30, ' '詩篇 115:12-18' ], 275: [False, '耶利米書 4:10-31, 耶利米書 5, 腓立比書 3, 腓立比書 4:1, 詩篇 ' '116:1-11'], 276: [False, '耶利米書 6, 耶利米書 7:1-29, 腓立比書 4:2-23, 箴言 24:5-14'], 277: [ False, '耶利米書 7:30-34, 耶利米書 8, 耶利米書 9:1-16, 歌羅西書 1:1-23, ' '詩篇 116:12-19' ], 278: [ False, '耶利米書 9:17-26, 耶利米書 10, 耶利米書 11:1-17, 歌羅西書 1:24-29, ' '歌羅西書 2:1-5, 詩篇 117:1-2' ], 279: [ False, '耶利米書 11:18-23, 耶利米書 12, 耶利米書 13, 歌羅西書 2:6-23, 詩篇 ' '118:1-16' ], 280: [False, '耶利米書 14, 耶利米書 15, 歌羅西書 3, 歌羅西書 4:1, 箴言 ' '24:15-22'], 281: [False, '耶利米書 16, 耶利米書 17, 歌羅西書 4:2-18, 詩篇 118:17-29'], 282: [ False, '耶利米書 18, 耶利米書 19, 耶利米書 20, 帖撒羅尼迦前書 1, 帖撒羅尼迦前書 2:1-16, 詩篇 119:1-8' ], 283: [ False, '耶利米書 21, 耶利米書 22, 耶利米書 23:1-8, 帖撒羅尼迦前書 2:17-19, 帖撒羅尼迦前書 3, 詩篇 119:9-16' ], 284: [ False, '耶利米書 23:9-40, 耶利米書 24, 耶利米書 25:1-14, 帖撒羅尼迦前書 4, ' '箴言 24:23-34' ], 285: [False, '耶利米書 25:15-38, 耶利米書 26, 帖撒羅尼迦前書 5, 詩篇 119:17-24'], 286: [ False, '耶利米書 27, 耶利米書 28, 耶利米書 29:1-23, 帖撒羅尼迦後書 1, 詩篇 ' '119:25-32' ], 287: [ False, '耶利米書 29:24-32, 耶利米書 30, 耶利米書 31:1-14, 帖撒羅尼迦後書 2, ' '詩篇 119:33-40' ], 288: [False, '耶利米書 31:15-40, 耶利米書 32:1-25, 帖撒羅尼迦後書 3, 箴言 ' '25:1-10'], 289: [ False, '耶利米書 32:26-44, 耶利米書 33, 耶利米書 34, 提摩太前書 1, 詩篇 ' '119:41-48' ], 290: [False, '耶利米書 35, 耶利米書 36, 耶利米書 37, 提摩太前書 2, 詩篇 119:49-56'], 291: [ False, '耶利米書 38, 耶利米書 39, 耶利米書 40:1-6, 提摩太前書 3, 詩篇 ' '119:57-64' ], 292: [ False, '耶利米書 40:7-16, 耶利米書 41, 耶利米書 42, 提摩太前書 4, 箴言 ' '25:11-20' ], 293: [ False, '耶利米書 43, 耶利米書 44, 耶利米書 45, 提摩太前書 5, 提摩太前書 6:1-2, ' '詩篇 119:65-72' ], 294: [False, '耶利米書 46, 耶利米書 47, 提摩太前書 6:3-21, 詩篇 119:73-80'], 295: [False, '耶利米書 48, 耶利米書 49:1-6, 提摩太後書 1, 詩篇 119:81-88'], 296: [ False, '耶利米書 49:7-39, 耶利米書 50:1-10, 提摩太後書 2, 箴言 25:21-28, ' '箴言 26:1-2' ], 297: [False, '耶利米書 50:11-46, 耶利米書 51:1-14, 提摩太後書 3, 詩篇 119:89-96'], 298: [False, '耶利米書 51:15-64, 提摩太後書 4, 詩篇 119:97-104'], 299: [False, '耶利米書 52, 提多書 1, 詩篇 119:105-112'], 300: [False, '哈巴谷書 1, 哈巴谷書 2, 哈巴谷書 3:1-19, 提多書 2, 箴言 26:3-12'], 301: [False, '耶利米哀歌 1, 耶利米哀歌 2:1-6, 提多書 3, 詩篇 119:113-120'], 302: [False, '耶利米哀歌 2:7-27, 耶利米哀歌 3:1-39, 腓利門書 1, 詩篇 ' '119:121-128'], 303: [ False, '耶利米哀歌 3:40-66, 耶利米哀歌 4, 耶利米哀歌 5, 希伯來書 1, 詩篇 ' '119:129-136' ], 304: [False, '俄巴底亞書 1, 希伯來書 2, 箴言 26:13-22'], 305: [False, '約珥書 1, 約珥書 2:1-17, 希伯來書 3, 詩篇 119:137-144'], 306: [False, '約珥書 2:18-32, 約珥書 3, 希伯來書 4:1-13, 詩篇 119:145-152'], 307: [ False, '以西結書 1, 以西結書 2, 以西結書 3, 希伯來書 4:14-16, 希伯來書 5:1-10, ' '詩篇 119:153-160' ], 308: [ False, '以西結書 4, 以西結書 5, 以西結書 6, 希伯來書 5:11-14, 希伯來書 6:1-12, ' '箴言 26:23-28, 箴言 27:1-4' ], 309: [ False, '以西結書 7, 以西結書 8, 以西結書 9, 希伯來書 6:13-20, 希伯來書 7:1-10, ' '詩篇 119:161-168' ], 310: [ False, '以西結書 10, 以西結書 11, 以西結書 12, 希伯來書 7:11-28, 詩篇 ' '119:169-176' ], 311: [False, '以西結書 13, 以西結書 14, 以西結書 15, 希伯來書 8, 詩篇 120:1-7'], 312: [False, '以西結書 16, 希伯來書 9:1-15, 箴言 27:5-14'], 313: [False, '以西結書 17, 以西結書 18, 希伯來書 9:16-28, 詩篇 121:1-8'], 314: [False, '以西結書 19, 以西結書 20:1-44, 希伯來書 10:1-18, 詩篇 122:1-9'], 315: [ False, '以西結書 20:45-49, 以西結書 21, 以西結書 22:1-22, 希伯來書 10:19-39, 詩篇 ' '123:1-4' ], 316: [False, '以西結書 22:23-31, 以西結書 23, 希伯來書 11:1-16, 箴言 27:15-22'], 317: [False, '以西結書 24, 以西結書 25, 希伯來書 11:17-40, 詩篇 124:1-8'], 318: [False, '以西結書 26, 以西結書 27, 希伯來書 12:1-13, 詩篇 125:1-5'], 319: [False, '以西結書 28, 以西結書 29, 希伯來書 12:14-29, 詩篇 126:1-6'], 320: [False, '以西結書 30, 以西結書 31, 希伯來書 13, 箴言 27:23-27, 箴言 ' '28:1-6'], 321: [False, '以西結書 32, 以西結書 33:1-32, 雅各書 1, 詩篇 127:1-5'], 322: [False, '以西結書 33:21-33, 以西結書 34, 以西結書 35, 雅各書 2, 詩篇 128:1-6'], 323: [False, '以西結書 36, 以西結書 37, 雅各書 3, 詩篇 129:1-8'], 324: [False, '以西結書 38, 以西結書 39, 雅各書 4, 箴言 28:7-17'], 325: [False, '以西結書 40, 雅各書 5, 詩篇 130:1-8'], 326: [False, '以西結書 41, 以西結書 42, 彼得前書 1, 彼得前書 2:1-3, 詩篇 131:1-3'], 327: [False, '以西結書 43, 以西結書 44, 彼得前書 2:4-25, 詩篇 132:1-18'], 328: [False, '以西結書 45, 以西結書 46, 彼得前書 3, 箴言 28:18-28'], 329: [False, '以西結書 47, 以西結書 48, 彼得前書 4, 詩篇 133:1-3'], 330: [False, '但以理書 1, 但以理書 2:1-23, 彼得前書 5, 詩篇 134:1-3'], 331: [False, '但以理書 2:24-49, 但以理書 3:1-12, 彼得後書 1, 詩篇 135:1-12'], 332: [False, '但以理書 3:13-30, 但以理書 4:1-18, 彼得後書 2, 箴言 29:1-9'], 333: [False, '但以理書 4:19-37, 但以理書 5:1-16, 彼得後書 3, 詩篇 135:13-21'], 334: [False, '但以理書 5:17-31, 但以理書 6:1-28, 約翰一書 1, 約翰一書 2, 詩篇 136:1-12'], 335: [False, '但以理書 7, 但以理書 8:1-14, 約翰一書 2:12-27, 詩篇 136:13-26'], 336: [ False, '但以理書 8:15-27, 但以理書 9:1-19, 約翰一書 2:28-29, 約翰一書 3:1-10, 箴言 ' '29:10-18' ], 337: [ False, '但以理書 9:20-27, 但以理書 10, 但以理書 11:1, 約翰一書 3:11-24, 約翰一書 4:1-6, ' '詩篇 137:1-9' ], 338: [False, '但以理書 11:2-35, 約翰一書 4:7-21, 詩篇 138:1-8'], 339: [False, '但以理書 11:36-45, 但以理書 12, 約翰一書 5:1-21, 詩篇 139:1-10'], 340: [False, '哈該書 1, 哈該書 2:1-23, 約翰二書 1:1-13, 箴言 29:19-27'], 341: [ False, '撒迦利亞書 1, 撒迦利亞書 2, 撒迦利亞書 3, 撒迦利亞書 4, 約翰三書 1:1-14, ' '詩篇 139:11-16' ], 342: [ False, '撒迦利亞書 5, 撒迦利亞書 6, 撒迦利亞書 7, 撒迦利亞書 8, 猶大書 1:1-25, 詩篇 ' '139:17-24' ], 343: [False, '撒迦利亞書 9, 撒迦利亞書 10, 撒迦利亞書 11, 啟示錄 1, 詩篇 140:1-5'], 344: [ False, '撒迦利亞書 12, 撒迦利亞書 13, 撒迦利亞書 14, 啟示錄 2:1-17, 箴言 ' '30:1-10' ], 345: [ False, '以斯帖記 1, 以斯帖記 2:1-18, 啟示錄 2:18-29, 啟示錄 3:1-6, 詩篇 ' '140:6-13' ], 346: [ False, '以斯帖記 2:19-23, 以斯帖記 3, 以斯帖記 4, 以斯帖記 5, 啟示錄 3:7-22, 詩篇 ' '141:1-10' ], 347: [False, '以斯帖記 6, 以斯帖記 7, 以斯帖記 8, 啟示錄 4, 詩篇 142:1-11'], 348: [False, '以斯帖記 9, 以斯帖記 10, 啟示錄 5, 箴言 30:11-23'], 349: [False, '瑪拉基書 1, 瑪拉基書 2:1-16, 啟示錄 6, 詩篇 143:1-12'], 350: [False, '瑪拉基書 2:17, 瑪拉基書 3, 瑪拉基書 4, 啟示錄 7, 詩篇 144:1-8'], 351: [False, '以斯拉記 1, 以斯拉記 2:1-67, 啟示錄 8, 啟示錄 9:1-12, 詩篇 144:9-15'], 352: [ False, '以斯拉記 2:68-70, 以斯拉記 3, 以斯拉記 4:1-5, 啟示錄 9:13-21, 啟示錄 10, ' '箴言 30:24-33' ], 353: [False, '以斯拉記 4:6-24, 以斯拉記 5, 啟示錄 11, 詩篇 145:1-7'], 354: [False, '以斯拉記 6, 以斯拉記 7:1-10, 啟示錄 12, 啟示錄 13:1, 詩篇 145:8-13'], 355: [False, '以斯拉記 7:11-28, 以斯拉記 8:1-14, 啟示錄 13:1-18, 詩篇 145:13-21'], 356: [False, '以斯拉記 8:15-36, 以斯拉記 9:1-15, 啟示錄 14:1-13, 箴言 31:1-9'], 357: [False, '以斯拉記 10, 啟示錄 14:14-20, 啟示錄 15, 詩篇 146:1-10'], 358: [False, '尼希米記 1, 尼希米記 2, 啟示錄 16, 詩篇 147:1-11'], 359: [False, '尼希米記 3, 尼希米記 4, 啟示錄 17, 詩篇 147:12-20'], 360: [ False, '尼希米記 5, 尼希米記 6, 尼希米記 7:1-3, 啟示錄 18:1-17, 箴言 ' '31:10-20' ], 361: [ False, '尼希米記 7:4-73, 尼希米記 8, 啟示錄 18:17-24, 啟示錄 19:1-10, ' '詩篇 148:1-6' ], 362: [False, '尼希米記 9:1-37, 啟示錄 19:11-21, 詩篇 148:7-14'], 363: [ False, '尼希米記 9:38, 尼希米記 10, 尼希米記 11:1-21, 啟示錄 20, 詩篇 ' '149:1-9' ], 364: [False, '尼希米記 11:22-36, 尼希米記 12:1-47, 啟示錄 21, 箴言 31:21-31'], 365: [False, '尼希米記 13, 啟示錄 22, 詩篇 150:1-6'], } translation = ( "聖經閱讀計劃", "今天是 ", "搜索:", "聖經視窗頁籤中開啓", "隱藏已經閱讀的經文", "顯示已經閱讀的經文", "重新設置", "儲存閱讀進度", "第", "天", "您的閱讀進度儲存在下面這個檔案:", "沒法把您的閱讀進度儲存在您現在使用的電腦上!", ) def __init__(self, parent): super().__init__() self.parent = parent # set title self.setWindowTitle(self.translation[0]) self.setMinimumSize(830, 500) # set variables self.setupVariables() # setup interface self.setupUI() def setupVariables(self): import copy, os from datetime import date self.today = date.today() self.todayNo = int(format(self.today, '%j')) if self.todayNo > 365: self.todayNo = 365 self.progressFile = os.path.join(os.getcwd(), "plugins", "menu", "{0}.txt".format(self.translation[0])) if os.path.isfile(self.progressFile): from ast import literal_eval with open(self.progressFile, "r") as fileObj: self.plan = literal_eval(fileObj.read()) else: self.plan = copy.deepcopy(self.template) self.hideCheckedItems = False def setupUI(self): from qtpy.QtGui import QStandardItemModel from qtpy.QtWidgets import (QPushButton, QLabel, QListView, QAbstractItemView, QHBoxLayout, QVBoxLayout, QLineEdit) mainLayout = QVBoxLayout() readingListLayout = QVBoxLayout() readingListLayout.addWidget(QLabel(self.translation[0])) readingListLayout.addWidget( QLabel("{0}{1}".format(self.translation[1], self.today))) filterLayout = QHBoxLayout() filterLayout.addWidget(QLabel(self.translation[2])) self.filterEntry = QLineEdit() self.filterEntry.textChanged.connect(self.resetItems) filterLayout.addWidget(self.filterEntry) readingListLayout.addLayout(filterLayout) self.readingList = QListView() self.readingList.setEditTriggers(QAbstractItemView.NoEditTriggers) self.readingListModel = QStandardItemModel(self.readingList) self.readingList.setModel(self.readingListModel) self.resetItems() self.readingListModel.itemChanged.connect(self.itemChanged) #print(self.readingList.currentIndex().row()) #self.readingList.selectionModel().selectionChanged.connect(self.function) readingListLayout.addWidget(self.readingList) buttonsLayout = QHBoxLayout() button = QPushButton(self.translation[3]) button.clicked.connect(self.openInTabs) buttonsLayout.addWidget(button) self.hideShowButton = QPushButton(self.translation[4]) self.hideShowButton.clicked.connect(self.hideShowCheckedItems) buttonsLayout.addWidget(self.hideShowButton) button = QPushButton(self.translation[6]) button.clicked.connect(self.resetAllItems) buttonsLayout.addWidget(button) button = QPushButton(self.translation[7]) button.clicked.connect(self.saveProgress) buttonsLayout.addWidget(button) mainLayout.addLayout(readingListLayout) mainLayout.addLayout(buttonsLayout) self.setLayout(mainLayout) def itemChanged(self, standardItem): from qtpy.QtCore import Qt key = int(standardItem.text().split(".")[0]) if standardItem.checkState() is Qt.CheckState.Checked: self.plan[key][0] = True elif standardItem.checkState() is Qt.CheckState.Unchecked: self.plan[key][0] = False if self.hideCheckedItems: self.resetItems() def resetItems(self): from qtpy.QtGui import QStandardItem from qtpy.QtCore import Qt # Empty the model before reset self.readingListModel.clear() # Reset index = 0 todayIndex = None filterEntry = self.filterEntry.text() for key, value in self.plan.items(): checked, passages = value if not (self.hideCheckedItems and checked) and ( filterEntry == "" or (filterEntry != "" and filterEntry.lower() in passages.lower())): item = QStandardItem("{0}. {1}".format(key, passages)) item.setToolTip("{0}{1}{2}".format(self.translation[8], key, self.translation[9])) if key == self.todayNo: todayIndex = index item.setCheckable(True) item.setCheckState(Qt.CheckState.Checked if checked else Qt. CheckState.Unchecked) self.readingListModel.appendRow(item) index += 1 if todayIndex is not None: self.readingList.setCurrentIndex( self.readingListModel.index(todayIndex, 0)) def hideShowCheckedItems(self): self.hideCheckedItems = not self.hideCheckedItems self.resetItems() self.hideShowButton.setText(self.translation[5] if self. hideCheckedItems else self.translation[4]) def resetAllItems(self): import copy self.plan = copy.deepcopy(self.template) self.resetItems() def translateIntoChinese(self): import copy, pprint from BibleBooks import BibleBooks plan = copy.deepcopy(self.template) filePath = "{0}_zh".format(self.progressFile) with open(filePath, "w", encoding="utf-8") as fileObj: fileObj.write(pprint.pformat(plan)) with open(filePath, "r") as fileObj: text = fileObj.read() translateDict = {} bookNames = [] for key, value in BibleBooks.eng.items(): bookName = value[-1] bookNames.append(bookName) translateDict[bookName] = BibleBooks.sc[key][-1] bookNames = sorted(bookNames, key=len, reverse=True) #print(bookNames) for name in bookNames: text = text.replace(name, translateDict[name]) text = text.replace("Psalm", "诗篇") with open(filePath, "w", encoding="utf-8") as fileObj: fileObj.write(text) def saveProgress(self): import pprint from qtpy.QtWidgets import QMessageBox try: with open(self.progressFile, "w", encoding="utf-8") as fileObj: fileObj.write(pprint.pformat(self.plan)) message = "{0}\n'{1}'".format(self.translation[10], self.progressFile) except: message = self.translation[11] QMessageBox.information(self, self.translation[0], message) def openInTabs(self): dayNo = self.readingList.currentIndex().row() + 1 todayReading = self.plan[dayNo][-1].split(", ") openBibleWindowContentOnNextTab = config.openBibleWindowContentOnNextTab config.openBibleWindowContentOnNextTab = True for reading in todayReading: command = "MAIN:::{0}".format(reading) self.parent.runTextCommand(command) config.openBibleWindowContentOnNextTab = openBibleWindowContentOnNextTab self.close()
class Switcher(QDialog): """ A multi purpose switcher. Example ------- SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] SwitcherSeparator: [---------------------------------------] SwitcherItem: [title description <shortcut> section] SwitcherItem: [title description <shortcut> section] """ # Search/Filter text changes sig_text_changed = Signal(TEXT_TYPES[-1]) # List item selected, mode and cleaned search text sig_item_selected = Signal( object, TEXT_TYPES[-1], TEXT_TYPES[-1], ) sig_mode_selected = Signal(TEXT_TYPES[-1]) _MIN_WIDTH = 500 def __init__(self, parent, help_text=None, item_styles=ITEM_STYLES, item_separator_styles=ITEM_SEPARATOR_STYLES): """Multi purpose switcher.""" super(Switcher, self).__init__(parent) self._visible_rows = 0 self._modes = {} self._mode_on = '' self._item_styles = item_styles self._item_separator_styles = item_separator_styles # Widgets self.edit = QLineEdit(self) self.list = QListView(self) self.model = QStandardItemModel(self.list) self.proxy = SwitcherProxyModel(self.list) self.filter = KeyPressFilter() # Widgets setup # self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint) self.setWindowOpacity(0.95) self.edit.installEventFilter(self.filter) self.edit.setPlaceholderText(help_text if help_text else '') self.list.setMinimumWidth(self._MIN_WIDTH) self.list.setItemDelegate(HTMLDelegate(self)) self.list.setFocusPolicy(Qt.NoFocus) self.list.setSelectionBehavior(self.list.SelectRows) self.list.setSelectionMode(self.list.SingleSelection) self.proxy.setSourceModel(self.model) self.list.setModel(self.proxy) # Layout layout = QVBoxLayout() layout.addWidget(self.edit) layout.addWidget(self.list) self.setLayout(layout) # Signals self.filter.sig_up_key_pressed.connect(self.previous_row) self.filter.sig_down_key_pressed.connect(self.next_row) self.filter.sig_enter_key_pressed.connect(self.enter) self.edit.textChanged.connect(self.setup) self.edit.textChanged.connect(self.sig_text_changed) self.edit.returnPressed.connect(self.enter) self.list.clicked.connect(self.enter) self.list.clicked.connect(self.edit.setFocus) # --- Helper methods def _add_item(self, item): """Perform common actions when adding items.""" item.set_width(self._MIN_WIDTH) self.model.appendRow(item) self.set_current_row(0) self._visible_rows = self.model.rowCount() self.setup_sections() # --- API def clear(self): """Remove all items from the list and clear the search text.""" self.set_placeholder_text('') self.model.beginResetModel() self.model.clear() self.model.endResetModel() def set_placeholder_text(self, text): """Set the text appearing on the empty line edit.""" self.edit.setPlaceholderText(text) def add_mode(self, token, description): """Add mode by token key and description.""" if len(token) == 1: self._modes[token] = description else: raise Exception('Token must be of length 1!') def remove_mode(self, token): """Remove mode by token key.""" if token in self._modes: self._modes.pop(token) def clear_modes(self): """Delete all modes spreviously defined.""" del self._modes self._modes = {} def add_item(self, icon=None, title=None, description=None, shortcut=None, section=None, data=None, tool_tip=None, action_item=False): """Add switcher list item.""" item = SwitcherItem(parent=self.list, icon=icon, title=title, description=description, data=data, shortcut=shortcut, section=section, action_item=action_item, tool_tip=tool_tip, styles=self._item_styles) self._add_item(item) def add_separator(self): """Add separator item.""" item = SwitcherSeparatorItem(parent=self.list, styles=self._item_separator_styles) self._add_item(item) def setup(self): """Set-up list widget content based on the filtering.""" # Check exited mode mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() # Check exited mode if mode and self.search_text() == '': self._mode_on = '' self.sig_mode_selected.emit(self._mode_on) return # Check entered mode for key in self._modes: if self.search_text().startswith(key) and not mode: self._mode_on = key self.sig_mode_selected.emit(key) return # Filter by text titles = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): title = item.get_title() else: title = '' titles.append(title) search_text = clean_string(search_text) scores = get_search_scores(to_text_string(search_text), titles, template=u"<b>{0}</b>") self._visible_rows = self.model.rowCount() for idx, score in enumerate(scores): title, rich_title, score_value = score item = self.model.item(idx) if not self._is_separator(item): item.set_rich_title(rich_title) item.set_score(score_value) proxy_index = self.proxy.mapFromSource(self.model.index(idx, 0)) if not item.is_action_item(): self.list.setRowHidden(proxy_index.row(), score_value == -1) if score_value == -1: self._visible_rows -= 1 if self._visible_rows: self.set_current_row(0) else: self.set_current_row(-1) self.setup_sections() def setup_sections(self): """Set-up which sections appear on the item list.""" mode = self._mode_on if mode: search_text = self.search_text()[len(mode):] else: search_text = self.search_text() if search_text: for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): item.set_section_visible(False) else: sections = [] for row in range(self.model.rowCount()): item = self.model.item(row) if isinstance(item, SwitcherItem): sections.append(item.get_section()) item.set_section_visible(bool(search_text)) else: sections.append('') if row != 0: visible = sections[row] != sections[row - 1] if not self._is_separator(item): item.set_section_visible(visible) else: item.set_section_visible(True) self.proxy.sortBy('_score') # --- Qt overrides # ------------------------------------------------------------------------ @Slot() @Slot(QListWidgetItem) def enter(self, itemClicked=None): """Override Qt method.""" row = self.current_row() model_index = self.proxy.mapToSource(self.proxy.index(row, 0)) item = self.model.item(model_index.row()) if item: mode = self._mode_on self.sig_item_selected.emit(item, mode, self.search_text()[len(mode):]) def accept(self): """Override Qt method.""" super(Switcher, self).accept() def resizeEvent(self, event): """Override Qt method.""" super(Switcher, self).resizeEvent(event) # --- Helper methods: Lineedit widget def search_text(self): """Get the normalized (lowecase) content of the search text.""" return to_text_string(self.edit.text()).lower() def set_search_text(self, string): """Set the content of the search text.""" self.edit.setText(string) # --- Helper methods: List widget def _is_separator(self, item): """Check if item is an separator item (SwitcherSeparatorItem).""" return isinstance(item, SwitcherSeparatorItem) def _select_row(self, steps): """Select row in list widget based on a number of steps with direction. Steps can be positive (next rows) or negative (previous rows). """ row = self.current_row() + steps if 0 <= row < self.count(): self.set_current_row(row) def count(self): """Get the item count in the list widget.""" return self._visible_rows def current_row(self): """Return the current selected row in the list widget.""" return self.list.currentIndex().row() def set_current_row(self, row): """Set the current selected row in the list widget.""" index = self.model.index(row, 0) selection_model = self.list.selectionModel() # https://doc.qt.io/qt-5/qitemselectionmodel.html#SelectionFlag-enum selection_model.setCurrentIndex(index, selection_model.ClearAndSelect) def previous_row(self): """Select previous row in list widget.""" steps = 1 prev_row = self.current_row() - steps if prev_row == -1: self.set_current_row(self.count() - 1) else: if prev_row >= 0: # Need to map the filtered list to the actual model items list_index = self.proxy.index(prev_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if self._is_separator(item): steps += 1 self._select_row(-steps) def next_row(self): """Select next row in list widget.""" steps = 1 next_row = self.current_row() + steps # Need to map the filtered list to the actual model items list_index = self.proxy.index(next_row, 0) model_index = self.proxy.mapToSource(list_index) item = self.model.item(model_index.row(), 0) if next_row >= self.count(): self.set_current_row(0) else: if item: if self._is_separator(item): steps += 1 self._select_row(steps)