class charsPanel(QWidget): def __init__(self, parent=None): super(charsPanel, self).__init__(parent) # Do the layout: refresh button and filter popup at the top, # with a table below. mainLayout = QVBoxLayout() self.setLayout(mainLayout) topLayout = QHBoxLayout() mainLayout.addLayout(topLayout, 0) self.refreshButton = QPushButton("Refresh") self.filterMenu = QComboBox() topLayout.addWidget(self.refreshButton, 0) topLayout.addStretch(1) topLayout.addWidget(self.filterMenu, 0) self.view = QTableView() self.view.setCornerButtonEnabled(False) self.view.setWordWrap(False) self.view.setAlternatingRowColors(True) mainLayout.addWidget(self.view, 1) # Set up the table model/view. Pass to the model a pointer # to the view so it can query the row under the mouse. self.model = myTableModel(view=self.view) #Interpose a sort filter proxy between the view and the model. self.proxy = mySortFilterProxy(self) self.proxy.setSourceModel(self.model) self.view.setModel(self.proxy) # Hook up the refresh button clicked signal to refresh below self.connect(self.refreshButton, SIGNAL("clicked()"), self.refresh) # Populate the filter popup with rows: # 0 : All - no filter # 1 : not 7-bit - show only things not in the 7-bit code # 2 : not Latin-1 - show only things outside Latin-1 self.filterMenu.addItem(QString(u"All")) self.filterMenu.addItem(QString(u"\u00ac" + u" 7-bit")) self.filterMenu.addItem(QString(u"\u00ac" + u" Latin-1")) # The filters refer to these properties, called with a QChar C self.lambdaAll = lambda C: True self.lambdaNotAscii = lambda C: (C.unicode() < 32) or (C.unicode() > 126) self.lambdaNotLatin = lambda C: (C.toLatin1() == b'\x00') self.filterLambda = self.lambdaAll # Connect a user-selection in the popup to our filter method. self.connect(self.filterMenu, SIGNAL("activated(int)"), self.filter) # Connect doubleclicked from our table view to self.findThis self.connect(self.view, SIGNAL("doubleClicked(QModelIndex)"), self.findThis) # Connect the model reset signals to functions to place and clear # a status message. self.connect(self.model, SIGNAL("modelAboutToBeReset()"), self.sigResetStarting) self.connect(self.model, SIGNAL("modelReset()"), self.sigResetOver) # This slot receives a double-click on the table. Figure out which # character it is and get the Find panel set up to search for it. def findThis(self, qmi): rep = None if qmi.column() == 3: # doubleclick in entity column, put entity in the replace field rep = qmi.data(Qt.DisplayRole).toString() if qmi.column() != 0: # get reference to column 0 qmi = qmi.sibling(qmi.row(), 0) qs = qmi.data(Qt.DisplayRole).toString() # Call for a find with respect case on, whole word and regex off IMC.findPanel.censusFinder(qs, rep, False, False) # this slot gets the activated(row) signal from the combo-box. # Based on the row, set self.filterLambda to a lambda that will # accept or reject a given QChar value. def filter(self, row): if row == 1: self.filterLambda = self.lambdaNotAscii elif row == 2: self.filterLambda = self.lambdaNotLatin else: self.filterLambda = self.lambdaAll self.model.reset() # This slot receives the main window's docWillChange signal. # It comes with a file path but we can ignore that. def docWillChange(self): #self.view.setSortingEnabled(False) self.model.beginResetModel() # Subroutine to reset the visual appearance of the table view, # invoked on table reset or docHasChanged because on instantiation # we have no data until a file is opened. def setUpTableView(self): self.view.resizeColumnsToContents() self.view.horizontalHeader().setStretchLastSection(True) self.view.resizeRowsToContents() self.view.setSortingEnabled(True) # This slot receives the main window's docHasChanged signal. # Let the table view populate with all-new metadata (or empty # data if the command was File>New). def docHasChanged(self): self.model.endResetModel() self.setUpTableView() # This slot receives the click of the refresh button. Tell the # model we are resetting everything so the view will suck up new # data. Then call our editor to rebuild the metadata. def refresh(self): #self.view.setSortingEnabled(False) self.model.beginResetModel() IMC.editWidget.rebuildMetadata() self.model.endResetModel() self.setUpTableView() # The model emits signals when it is starting to rebuild the table # and when it has finished rebuilding the table. Use these to put up # a status message, as the wait can be significant. def sigResetStarting(self): pqMsgs.showStatusMsg(QString(u"Rebuilding Character Table...")) def sigResetOver(self): pqMsgs.clearStatusMsg()
class pagesPanel(QWidget): def __init__(self, parent=None): super(pagesPanel, self).__init__(parent) # The layout is very basic, the table with an Update button. mainLayout = QVBoxLayout() self.setLayout(mainLayout) hlayout = QHBoxLayout() self.updateButton = QPushButton("Update") self.insertText = QLineEdit() self.insertText.setFont(pqMsgs.getMonoFont()) self.insertButton = QPushButton("Insert") hlayout.addWidget(self.updateButton,0) hlayout.addWidget(self.insertText,1) # text gets all available room hlayout.addWidget(self.insertButton,0) mainLayout.addLayout(hlayout) self.view = QTableView() self.view.setCornerButtonEnabled(False) self.view.setWordWrap(False) self.view.setAlternatingRowColors(True) self.view.setSortingEnabled(False) self.c1Delegate = formatDelegate() self.view.setItemDelegateForColumn(1,self.c1Delegate) self.c2Delegate = actionDelegate() self.view.setItemDelegateForColumn(2,self.c2Delegate) self.c3Delegate = folioDelegate() self.view.setItemDelegateForColumn(3,self.c3Delegate) mainLayout.addWidget(self.view,1) # Set up the table model/view. self.model = myTableModel() self.view.setModel(self.model) # Connect the double-clicked signal of the view self.connect(self.view, SIGNAL("doubleClicked(QModelIndex)"), self.goToRow) # Connect the update button to the model's update method self.connect(self.updateButton, SIGNAL("clicked()"),self.model.updateFolios) # Connect the insert button to our insert method self.connect(self.insertButton, SIGNAL("clicked()"),self.insertMarkers) # This slot receives a double-click from the table view, # passing an index. If the click is in column 0, the scan number, # get the row; use it to get a text cursor from the page table # and make that the editor's cursor, thus moving to the top of that page. # Double-click on cols 1-3 initiates editing and maybe someday a # doubleclick on column 5 will do something with the proofer info. def goToRow(self,index): if index.column() == 0: tc = IMC.pageTable.getCursor(index.row()) IMC.editWidget.setTextCursor(tc) IMC.editWidget.setFocus(Qt.TabFocusReason) # This slot receives the main window's docWillChange signal. # It comes with a file path but we can ignore that. def docWillChange(self): self.model.beginResetModel() # Subroutine to reset the visual appearance of the table view, # invoked on table reset because on instantiation we have no table. def setUpTableView(self): # Header text is supplied by the table model headerData method # Here we are going to set the column widths of the first 4 # columns to a uniform 7 ens each based on the current font. # However, at least on Mac OS, the headers are rendered with a # much smaller font than the data, so we up it by 50%. hdr = self.view.horizontalHeader() pix = hdr.fontMetrics().width(QString("9999999")) hdr.resizeSection(0,pix) hdr.resizeSection(3,pix) pix += pix/2 hdr.resizeSection(1,pix) hdr.resizeSection(2,pix) self.view.resizeColumnToContents(4) # This slot receives the main window's docHasChanged signal. # Let the table view populate with all-new metadata (or empty # data if the command was File>New). def docHasChanged(self): self.model.endResetModel() self.setUpTableView() # On the Insert button being pressed, make some basic sanity checks # and get user go-ahead then insert the given text at the head of # every page. def insertMarkers(self): # Copy the text and if it is empty, complain and exit. qi = QString(self.insertText.text()) if qi.isEmpty() : pqMsgs.warningMsg("No insert text specified") return # See how many pages are involved: all the ones that aren't marked skip n = 0 for i in range(IMC.pageTable.size()): if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip : n += 1 if n == 0 : # page table empty or all rows marked skip pqMsgs.warningMsg("No pages to give folios to") return m = "Insert this string at the top of {0} pages?".format(n) b = pqMsgs.okCancelMsg(QString(m),pqMsgs.trunc(qi,35)) if b : # Convert any '\n' in the text to the QT line delimiter char # we do this in the copy so the lineEdit text doesn't change qi.replace(QString(u'\\n'),QString(IMC.QtLineDelim)) # get a cursor on the edit document tc = QTextCursor(IMC.editWidget.textCursor()) tc.beginEditBlock() # start single undoable operation # Working from the end of the document backward, go to the # top of each page and insert the string for i in reversed( range( IMC.pageTable.size() ) ) : if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip : # Note the page's start position and set our work cursor to it pos = IMC.pageTable.getCursor(i).position() tc.setPosition(pos) # Make a copy of the insert string replacing %f with this folio f = IMC.pageTable.getDisplay(i) qf = QString(qi) qf.replace(QString(u'%f'),f,Qt.CaseInsensitive) tc.insertText(qf) # The insertion goes in ahead of the saved cursor position so now # it points after the inserted string. Put it back where it was. IMC.pageTable.setPosition(i, pos) tc.endEditBlock() # wrap up the undo op
class pagesPanel(QWidget): def __init__(self, parent=None): super(pagesPanel, self).__init__(parent) # The layout is very basic, the table with an Update button. mainLayout = QVBoxLayout() self.setLayout(mainLayout) hlayout = QHBoxLayout() self.updateButton = QPushButton("Update") self.insertText = QLineEdit() self.insertText.setFont(pqMsgs.getMonoFont()) self.insertButton = QPushButton("Insert") hlayout.addWidget(self.updateButton, 0) hlayout.addWidget(self.insertText, 1) # text gets all available room hlayout.addWidget(self.insertButton, 0) mainLayout.addLayout(hlayout) self.view = QTableView() self.view.setCornerButtonEnabled(False) self.view.setWordWrap(False) self.view.setAlternatingRowColors(True) self.view.setSortingEnabled(False) self.c1Delegate = formatDelegate() self.view.setItemDelegateForColumn(1, self.c1Delegate) self.c2Delegate = actionDelegate() self.view.setItemDelegateForColumn(2, self.c2Delegate) self.c3Delegate = folioDelegate() self.view.setItemDelegateForColumn(3, self.c3Delegate) mainLayout.addWidget(self.view, 1) # Set up the table model/view. self.model = myTableModel() self.view.setModel(self.model) # Connect the double-clicked signal of the view self.connect(self.view, SIGNAL("doubleClicked(QModelIndex)"), self.goToRow) # Connect the update button to the model's update method self.connect(self.updateButton, SIGNAL("clicked()"), self.model.updateFolios) # Connect the insert button to our insert method self.connect(self.insertButton, SIGNAL("clicked()"), self.insertMarkers) # This slot receives a double-click from the table view, # passing an index. If the click is in column 0, the scan number, # get the row; use it to get a text cursor from the page table # and make that the editor's cursor, thus moving to the top of that page. # Double-click on cols 1-3 initiates editing and maybe someday a # doubleclick on column 5 will do something with the proofer info. def goToRow(self, index): if index.column() == 0: tc = IMC.pageTable.getCursor(index.row()) IMC.editWidget.setTextCursor(tc) IMC.editWidget.setFocus(Qt.TabFocusReason) # This slot receives the main window's docWillChange signal. # It comes with a file path but we can ignore that. def docWillChange(self): self.model.beginResetModel() # Subroutine to reset the visual appearance of the table view, # invoked on table reset because on instantiation we have no table. def setUpTableView(self): # Header text is supplied by the table model headerData method # Here we are going to set the column widths of the first 4 # columns to a uniform 7 ens each based on the current font. # However, at least on Mac OS, the headers are rendered with a # much smaller font than the data, so we up it by 50%. hdr = self.view.horizontalHeader() pix = hdr.fontMetrics().width(QString("9999999")) hdr.resizeSection(0, pix) hdr.resizeSection(3, pix) pix += pix / 2 hdr.resizeSection(1, pix) hdr.resizeSection(2, pix) self.view.resizeColumnToContents(4) # This slot receives the main window's docHasChanged signal. # Let the table view populate with all-new metadata (or empty # data if the command was File>New). def docHasChanged(self): self.model.endResetModel() self.setUpTableView() # On the Insert button being pressed, make some basic sanity checks # and get user go-ahead then insert the given text at the head of # every page. def insertMarkers(self): # Copy the text and if it is empty, complain and exit. qi = QString(self.insertText.text()) if qi.isEmpty(): pqMsgs.warningMsg("No insert text specified") return # See how many pages are involved: all the ones that aren't marked skip n = 0 for i in range(IMC.pageTable.size()): if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip: n += 1 if n == 0: # page table empty or all rows marked skip pqMsgs.warningMsg("No pages to give folios to") return m = "Insert this string at the top of {0} pages?".format(n) b = pqMsgs.okCancelMsg(QString(m), pqMsgs.trunc(qi, 35)) if b: # Convert any '\n' in the text to the QT line delimiter char # we do this in the copy so the lineEdit text doesn't change qi.replace(QString(u'\\n'), QString(IMC.QtLineDelim)) # get a cursor on the edit document tc = QTextCursor(IMC.editWidget.textCursor()) tc.beginEditBlock() # start single undoable operation # Working from the end of the document backward, go to the # top of each page and insert the string for i in reversed(range(IMC.pageTable.size())): if IMC.pageTable.getAction(i) != IMC.FolioRuleSkip: # Note the page's start position and set our work cursor to it pos = IMC.pageTable.getCursor(i).position() tc.setPosition(pos) # Make a copy of the insert string replacing %f with this folio f = IMC.pageTable.getDisplay(i) qf = QString(qi) qf.replace(QString(u'%f'), f, Qt.CaseInsensitive) tc.insertText(qf) # The insertion goes in ahead of the saved cursor position so now # it points after the inserted string. Put it back where it was. IMC.pageTable.setPosition(i, pos) tc.endEditBlock() # wrap up the undo op
class charsPanel(QWidget): def __init__(self, parent=None): super(charsPanel, self).__init__(parent) # Do the layout: refresh button and filter popup at the top, # with a table below. mainLayout = QVBoxLayout() self.setLayout(mainLayout) topLayout = QHBoxLayout() mainLayout.addLayout(topLayout, 0) self.refreshButton = QPushButton("Refresh") self.filterMenu = QComboBox() topLayout.addWidget(self.refreshButton, 0) topLayout.addStretch(1) topLayout.addWidget(self.filterMenu, 0) self.view = QTableView() self.view.setCornerButtonEnabled(False) self.view.setWordWrap(False) self.view.setAlternatingRowColors(True) mainLayout.addWidget(self.view, 1) # Set up the table model/view. Pass to the model a pointer # to the view so it can query the row under the mouse. self.model = myTableModel(view=self.view) # Interpose a sort filter proxy between the view and the model. self.proxy = mySortFilterProxy(self) self.proxy.setSourceModel(self.model) self.view.setModel(self.proxy) # Hook up the refresh button clicked signal to refresh below self.connect(self.refreshButton, SIGNAL("clicked()"), self.refresh) # Populate the filter popup with rows: # 0 : All - no filter # 1 : not 7-bit - show only things not in the 7-bit code # 2 : not Latin-1 - show only things outside Latin-1 self.filterMenu.addItem(QString("All")) self.filterMenu.addItem(QString("\u00ac" + " 7-bit")) self.filterMenu.addItem(QString("\u00ac" + " Latin-1")) # The filters refer to these properties, called with a QChar C self.lambdaAll = lambda C: True self.lambdaNotAscii = lambda C: (C.unicode() < 32) or (C.unicode() > 126) self.lambdaNotLatin = lambda C: (C.toLatin1() == b"\x00") self.filterLambda = self.lambdaAll # Connect a user-selection in the popup to our filter method. self.connect(self.filterMenu, SIGNAL("activated(int)"), self.filter) # Connect doubleclicked from our table view to self.findThis self.connect(self.view, SIGNAL("doubleClicked(QModelIndex)"), self.findThis) # Connect the model reset signals to functions to place and clear # a status message. self.connect(self.model, SIGNAL("modelAboutToBeReset()"), self.sigResetStarting) self.connect(self.model, SIGNAL("modelReset()"), self.sigResetOver) # This slot receives a double-click on the table. Figure out which # character it is and get the Find panel set up to search for it. def findThis(self, qmi): rep = None if qmi.column() == 3: # doubleclick in entity column, put entity in the replace field rep = qmi.data(Qt.DisplayRole).toString() if qmi.column() != 0: # get reference to column 0 qmi = qmi.sibling(qmi.row(), 0) qs = qmi.data(Qt.DisplayRole).toString() # Call for a find with respect case on, whole word and regex off IMC.findPanel.censusFinder(qs, rep, False, False) # this slot gets the activated(row) signal from the combo-box. # Based on the row, set self.filterLambda to a lambda that will # accept or reject a given QChar value. def filter(self, row): if row == 1: self.filterLambda = self.lambdaNotAscii elif row == 2: self.filterLambda = self.lambdaNotLatin else: self.filterLambda = self.lambdaAll self.model.reset() # This slot receives the main window's docWillChange signal. # It comes with a file path but we can ignore that. def docWillChange(self): # self.view.setSortingEnabled(False) self.model.beginResetModel() # Subroutine to reset the visual appearance of the table view, # invoked on table reset or docHasChanged because on instantiation # we have no data until a file is opened. def setUpTableView(self): self.view.resizeColumnsToContents() self.view.horizontalHeader().setStretchLastSection(True) self.view.resizeRowsToContents() self.view.setSortingEnabled(True) # This slot receives the main window's docHasChanged signal. # Let the table view populate with all-new metadata (or empty # data if the command was File>New). def docHasChanged(self): self.model.endResetModel() self.setUpTableView() # This slot receives the click of the refresh button. Tell the # model we are resetting everything so the view will suck up new # data. Then call our editor to rebuild the metadata. def refresh(self): # self.view.setSortingEnabled(False) self.model.beginResetModel() IMC.editWidget.rebuildMetadata() self.model.endResetModel() self.setUpTableView() # The model emits signals when it is starting to rebuild the table # and when it has finished rebuilding the table. Use these to put up # a status message, as the wait can be significant. def sigResetStarting(self): pqMsgs.showStatusMsg(QString("Rebuilding Character Table...")) def sigResetOver(self): pqMsgs.clearStatusMsg()