def on_copy(self): select_group_dialog = QDialog(self) select_group_dialog.setWindowTitle(self.tr("Choose source group")) layout = QVBoxLayout(select_group_dialog) select_group_dialog.setLayout(layout) groups_list_view = QTableView(self) layout.addWidget(groups_list_view) groups_list_view.setModel(self.ds_model) groups_list_view.setColumnHidden(DSManagerModel.COLUMN_VISIBILITY, True) groups_list_view.horizontalHeader().setResizeMode(DSManagerModel.COLUMN_GROUP_DS, QHeaderView.Stretch) groups_list_view.setSelectionMode(QTableView.NoSelection) groups_list_view.setAlternatingRowColors(True) groups_list_view.setShowGrid(False) groups_list_view.verticalHeader().setResizeMode(QHeaderView.ResizeToContents) groups_list_view.verticalHeader().hide() groups_list_view.clicked.connect( lambda index: select_group_dialog.accept() \ if self.ds_model.isGroup(index) and \ index.column() == DSManagerModel.COLUMN_GROUP_DS \ else None ) if select_group_dialog.exec_() == QDialog.Accepted: group_info = self.ds_model.data(groups_list_view.currentIndex(), Qt.UserRole) group_info.id += "_copy" edit_dialog = GroupEditDialog() edit_dialog.setWindowTitle(self.tr('Create group from existing')) edit_dialog.fill_group_info(group_info) if edit_dialog.exec_() == QDialog.Accepted: self.feel_list() self.ds_model.resetModel()
class ConfSettingsWidget ( QWidget ): def __init__ ( self, conf, parent=None ): QWidget.__init__( self, parent ) self._rowHeight = 20 self._view = QTableView() self._view.setShowGrid ( False ) self._view.setAlternatingRowColors( True ) self._view.setSelectionBehavior ( QAbstractItemView.SelectRows ) #self._view.setSortingEnabled ( True ) #self._view.installEventFilter ( self ) horizontalHeader = self._view.horizontalHeader () horizontalHeader.setStretchLastSection ( True ) horizontalHeader.setMinimumSectionSize ( 150 ) horizontalHeader.setResizeMode ( QHeaderView.ResizeToContents ) horizontalHeader.setDefaultSectionSize ( 150 ) verticalHeader = self._view.verticalHeader (); verticalHeader.setVisible ( False ); verticalHeader.setDefaultSectionSize ( self._rowHeight ); self._baseModel = ConfSettingsModel( conf ) self._view.setModel( self._baseModel ); self._view.horizontalHeader().setStretchLastSection( True ); self._view.resizeColumnToContents( 0 ); peanoDataLayout = QGridLayout(); peanoDataLayout.addWidget( self._view, 0, 0, 1, 1 ); self.setLayout ( peanoDataLayout ); return
def createTable(self, header, tabledata): """creates a table""" gridlayout2 = QGridLayout(self) gridlayout2.setObjectName("gridlayout2") tableView = QTableView(self) tableView.setObjectName("tableView") gridlayout2.addWidget(tableView, 0, 0, 1, 1) self.__popUp = QMenu(tableView) self.__copyAction = QAction(self.tr("Copy data"), tableView) self.connect(self.__copyAction, SIGNAL("triggered()"), self.copy) self.__popUp.addAction(self.__copyAction) tableView.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(tableView, SIGNAL('customContextMenuRequested(QPoint)'), self.popUpMenu) # set the table model tm = TableModel(tabledata, header, self) tableView.setModel(tm) tableView.setAlternatingRowColors(True) # set the minimum size self.setMinimumSize(400, 300) # hide grid tableView.setShowGrid(True) # set the font #font = QFont("Courier New", 12) #self.tableView.setFont(font) # hide vertical header vh = tableView.verticalHeader() vh.setVisible(True) # set horizontal header properties hh = tableView.horizontalHeader() hh.setStretchLastSection(True) # set column width to fit contents tableView.resizeColumnsToContents() tableView.setSortingEnabled(True) tableView.sortByColumn(0, Qt.AscendingOrder) # set row height nrows = len(tabledata) for row in xrange(nrows): tableView.setRowHeight(row, 18)
def on_copy(self): select_group_dialog = QDialog(self) select_group_dialog.resize(300, 400) select_group_dialog.setWindowTitle(self.tr("Choose source group")) layout = QVBoxLayout(select_group_dialog) select_group_dialog.setLayout(layout) groups_list_view = QTableView(self) layout.addWidget(groups_list_view) groups_list_view.setModel(self.ds_model) groups_list_view.setColumnHidden(DSManagerModel.COLUMN_VISIBILITY, True) groups_list_view.horizontalHeader().setResizeMode( DSManagerModel.COLUMN_GROUP_DS, QHeaderView.Stretch) groups_list_view.setSelectionMode(QTableView.NoSelection) groups_list_view.setAlternatingRowColors(True) groups_list_view.setShowGrid(False) groups_list_view.verticalHeader().setResizeMode( QHeaderView.ResizeToContents) groups_list_view.verticalHeader().hide() groups_list_view.clicked.connect( lambda index: select_group_dialog.accept() \ if self.ds_model.isGroup(index) and \ index.column() == DSManagerModel.COLUMN_GROUP_DS \ else None ) if select_group_dialog.exec_() == QDialog.Accepted: group_info = self.ds_model.data(groups_list_view.currentIndex(), Qt.UserRole) group_info.id += "_copy" edit_dialog = GroupEditDialog() edit_dialog.setWindowTitle(self.tr('Create group from existing')) edit_dialog.fill_group_info(group_info) if edit_dialog.exec_() == QDialog.Accepted: self.feel_list() self.ds_model.resetModel()
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 EditorWidget(QWidget): ''' classdocs ''' def __init__(self, parent=None): ''' Constructor ''' QWidget.__init__(self, parent) self.mainLayout = QVBoxLayout() self.setLayout(self.mainLayout) # # Import Layout # self.importLayout = QHBoxLayout() self.mainLayout.addLayout(self.importLayout) self.importTypeComboBox = QComboBox() self.importTypeComboBox.addItem("RSS") self.importTypeComboBox.addItem("CSV") self.importLayout.addWidget(self.importTypeComboBox) # # RSS Layout # self.rssWidget = QWidget() self.rssLayout = QHBoxLayout() self.rssWidget.setLayout(self.rssLayout) self.rssLabel = QLabel("URL") self.rssLineEdit = QLineEdit() if hasattr(QLineEdit(), 'setPlaceholderText'): self.rssLineEdit.setPlaceholderText("http://www.example.com/rss") self.rssLabel.setBuddy(self.rssLineEdit) self.rssPushButton = QPushButton("Load talks from RSS") rss_icon = QIcon() rss_icon.addPixmap(QPixmap(":/multimedia/rss.png"), QIcon.Normal, QIcon.Off) self.rssPushButton.setIcon(rss_icon) self.rssLayout.addWidget(self.rssLabel) self.rssLayout.addWidget(self.rssLineEdit) self.rssLayout.addWidget(self.rssPushButton) self.importLayout.addWidget(self.rssWidget) # # CSV Layout # self.csvWidget = QWidget() self.csvWidget.hide() self.csvLayout = QHBoxLayout() self.csvWidget.setLayout(self.csvLayout) self.csvLabel = QLabel("File") self.csvLineEdit = QLineEdit() if sys.platform == 'win32': if hasattr(QLineEdit(), 'setPlaceholderText'): self.csvLineEdit.setPlaceholderText("C:\Example\Freeseer2011.csv") else: if hasattr(QLineEdit(), 'setPlaceholderText'): self.csvLineEdit.setPlaceholderText("/home/freeseer/Example/Freeseer2011.csv") self.csvLabel.setBuddy(self.csvLineEdit) self.csvFileSelectButton = QToolButton() self.csvFileSelectButton.setText("...") self.csvPushButton = QPushButton("Load talks from CSV") self.csvLayout.addWidget(self.csvLabel) self.csvLayout.addWidget(self.csvLineEdit) self.csvLayout.addWidget(self.csvFileSelectButton) self.csvLayout.addWidget(self.csvPushButton) self.importLayout.addWidget(self.csvWidget) # # Editor Layout # self.editorLayout = QHBoxLayout() self.mainLayout.addLayout(self.editorLayout) self.buttonsLayout = QVBoxLayout() self.editorLayout.addLayout(self.buttonsLayout) addIcon = QIcon.fromTheme("list-add") removeIcon = QIcon.fromTheme("list-remove") clearIcon = QIcon.fromTheme("edit-clear") closeIcon = QIcon.fromTheme("application-exit") self.addButton = QPushButton("Add") self.addButton.setIcon(addIcon) self.removeButton = QPushButton("Remove") self.removeButton.setIcon(removeIcon) self.clearButton = QPushButton("Clear") self.clearButton.setIcon(clearIcon) self.closeButton = QPushButton("Close") self.closeButton.setIcon(closeIcon) self.buttonsLayout.addWidget(self.addButton) self.buttonsLayout.addWidget(self.removeButton) self.buttonsLayout.addWidget(self.clearButton) self.buttonsLayout.addStretch(0) self.buttonsLayout.addWidget(self.closeButton) self.editor = QTableView() self.editor.setAlternatingRowColors(True) self.editor.setSortingEnabled(True) self.editorLayout.addWidget(self.editor) # # Widget Connections # self.connect(self.importTypeComboBox, SIGNAL('currentIndexChanged(const QString&)'), self.switch_import_plugin) def switch_import_plugin(self, plugin): self.rssWidget.hide() self.csvWidget.hide() if plugin == "RSS": self.rssWidget.show() elif plugin == "CSV": self.csvWidget.show()
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 GmApp(QMainWindow): def __init__(self): super(QMainWindow, self).__init__() self.setWindowTitle("GuloMail by GulonSoft") self.setWindowIcon(QIcon("g-square.png")) self.createActions() self.createStatusBar() self.createMenus() self.createToolbars() self.createWidgets() self.createLayouts() def createActions(self): self.newAction=QAction("&New", self, shortcut=QKeySequence.New, statusTip="New") self.sendReceiveAction=QAction("Send / &Receive", self, shortcut="F9", statusTip="Send / Receive") self.printAction=QAction("&Print...", self, shortcut="Ctrl+P", statusTip="Print") self.quitAction=QAction("&Quit", self, shortcut="Ctrl+Q", statusTip="Quit", triggered=self.close) self.copyAction=QAction("&Copy", self, statusTip="Copy", shortcut=QKeySequence.Copy) self.deleteAction=QAction("&Delete", self, statusTip="Delete Message") self.nextAction=QAction("Next &Unread Message", self, shortcut="Ctrl+]", statusTip="Next unread message") self.previousAction=QAction("P&revious Unread Message", self, shortcut="Ctrl+[", statusTip="Previous unread message") self.replyAction=QAction("&Reply", self, shortcut="Ctrl+R", statusTip="Reply to sender", triggered=self.reply) self.replyToAllAction=QAction("Reply to &All", self, shortcut="Ctrl+Shift+R", statusTip="Reply to all", triggered=self.replyToAll) self.forwardAction=QAction("&Forward", self, shortcut="Ctrl+F", statusTip="Forward") self.junkAction=QAction("Junk", self, shortcut="Ctrl+J", statusTip="Mark as Junk") self.notJunkAction=QAction("Not junk", self, shortcut="Shift+Ctrl+J", statusTip="Mark as Not Junk") self.contentsAction=QAction("&Contents", self, statusTip="Help Contents", shortcut="F1", triggered=self.helpContents) self.aboutAction=QAction("&About", self, statusTip="About GuloMail", triggered=self.about) self.cancelAction=QAction("&Cancel", self, statusTip="Cancel") def createStatusBar(self): self.statusBar() def createMenus(self): self.fileMenu=self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.sendReceiveAction) self.fileMenu.addAction(self.printAction) self.fileMenu.addAction(self.quitAction) self.editMenu=self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.copyAction) self.editMenu.addAction(self.deleteAction) self.viewMenu=self.menuBar().addMenu("&View") self.folderMenu=self.menuBar().addMenu("F&older") self.messageMenu=self.menuBar().addMenu("&Message") self.goToMenu=self.messageMenu.addMenu("&Go To") self.goToMenu.addAction(self.nextAction) self.goToMenu.addAction(self.previousAction) self.messageMenu.addAction(self.replyAction) self.messageMenu.addAction(self.replyToAllAction) self.messageMenu.addAction(self.forwardAction) self.markAsMenu=self.messageMenu.addMenu("Mar&k as...") self.markAsMenu.addAction(self.junkAction) self.markAsMenu.addAction(self.notJunkAction) self.searchMenu=self.menuBar().addMenu("&Search") self.helpMenu=self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.contentsAction) self.helpMenu.addAction(self.aboutAction) def createToolbars(self): self.toolbar=self.addToolBar('Main Toolbar') self.toolbar.setMovable(False) self.toolbar.addAction(self.newAction) self.toolbar.addSeparator() self.toolbar.addAction(self.sendReceiveAction) self.toolbar.addSeparator() self.toolbar.addAction(self.replyAction) self.toolbar.addAction(self.replyToAllAction) self.toolbar.addAction(self.forwardAction) self.toolbar.addSeparator() self.toolbar.addAction(self.printAction) self.toolbar.addAction(self.deleteAction) self.toolbar.addAction(self.junkAction) self.toolbar.addAction(self.notJunkAction) self.toolbar.addAction(self.cancelAction) self.toolbar.addSeparator() self.toolbar.addAction(self.previousAction) self.toolbar.addAction(self.nextAction) def createWidgets(self): ## Message Table self.table=QTableView() self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setGridStyle(Qt.NoPen) self.model = QStandardItemModel(8, 3, self) self.model.setHeaderData(0, Qt.Horizontal, "From") self.model.setHeaderData(1, Qt.Horizontal, "Subject") self.model.setHeaderData(2, Qt.Horizontal, "Received") self.table.setModel(self.model) self.selectionModel = QItemSelectionModel(self.model) self.selectionModel.SelectionFlag=0x0020 self.table.setSelectionModel(self.selectionModel) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setSortingEnabled(True) self.table.setAlternatingRowColors(True) ## Folder Tree View self.folderTree=QTreeWidget() self.folderTree.setColumnCount(1) self.folderTree.setHeaderLabel(QString('Folders')) self.treeItem=QTreeWidgetItem() self.treeItem.setText(0, 'Folders') self.inbox=QTreeWidgetItem() self.inbox.setText(0, 'Inbox') self.deletedItems=QTreeWidgetItem() self.deletedItems.setText(0, 'Deleted Items') self.drafts=QTreeWidgetItem() self.drafts.setText(0, 'Drafts') self.junk=QTreeWidgetItem() self.junk.setText(0, 'Junk') self.outbox=QTreeWidgetItem() self.outbox.setText(0, 'Outbox') self.sent=QTreeWidgetItem() self.sent.setText(0, 'Sent') self.treeItem.addChild(self.inbox) self.treeItem.addChild(self.deletedItems) self.treeItem.addChild(self.drafts) self.treeItem.addChild(self.junk) self.treeItem.addChild(self.outbox) self.treeItem.addChild(self.sent) self.folderTree.addTopLevelItem(self.treeItem) self.folderTree.expandAll() self.folderTree.setAnimated(True) self.folderTree.setMaximumWidth(150) ## Temp. placeholders self.textEdit=QTextEdit() self.textEdit2=QTextEdit() def createLayouts(self): self.mainSplitter=QSplitter() self.setCentralWidget(self.mainSplitter) self.mainSplitter.addWidget(self.folderTree) self.messageSplitter=QSplitter(Qt.Vertical) self.messageSplitter.addWidget(self.table) self.messageSplitter.addWidget(self.textEdit2) self.mainSplitter.addWidget(self.messageSplitter) def helpContents(self): print "Help" def reply(self): print "Reply" def replyToAll(self): print "Reply To All" def about(self): text=QString("GuloMail v0.1\n\n") text.append("GuloMail is a freeware email client written in Python using PyQt4 (Python bindings for Nokia's Qt)\n\n") text.append(QChar(0x00A9)) text.append("GulonSoft 2010\nhttp://www.gulon.co.uk/") QMessageBox.about(self, "About GuloMail", text)
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()
class GmApp(QMainWindow): def __init__(self): super(QMainWindow, self).__init__() self.setWindowTitle("GuloMail by GulonSoft") self.setWindowIcon(QIcon("g-square.png")) self.createActions() self.createStatusBar() self.createMenus() self.createToolbars() self.createWidgets() self.createLayouts() def createActions(self): self.newAction = QAction("&New", self, shortcut=QKeySequence.New, statusTip="New") self.sendReceiveAction = QAction("Send / &Receive", self, shortcut="F9", statusTip="Send / Receive") self.printAction = QAction("&Print...", self, shortcut="Ctrl+P", statusTip="Print") self.quitAction = QAction("&Quit", self, shortcut="Ctrl+Q", statusTip="Quit", triggered=self.close) self.copyAction = QAction("&Copy", self, statusTip="Copy", shortcut=QKeySequence.Copy) self.deleteAction = QAction("&Delete", self, statusTip="Delete Message") self.nextAction = QAction("Next &Unread Message", self, shortcut="Ctrl+]", statusTip="Next unread message") self.previousAction = QAction("P&revious Unread Message", self, shortcut="Ctrl+[", statusTip="Previous unread message") self.replyAction = QAction("&Reply", self, shortcut="Ctrl+R", statusTip="Reply to sender", triggered=self.reply) self.replyToAllAction = QAction("Reply to &All", self, shortcut="Ctrl+Shift+R", statusTip="Reply to all", triggered=self.replyToAll) self.forwardAction = QAction("&Forward", self, shortcut="Ctrl+F", statusTip="Forward") self.junkAction = QAction("Junk", self, shortcut="Ctrl+J", statusTip="Mark as Junk") self.notJunkAction = QAction("Not junk", self, shortcut="Shift+Ctrl+J", statusTip="Mark as Not Junk") self.contentsAction = QAction("&Contents", self, statusTip="Help Contents", shortcut="F1", triggered=self.helpContents) self.aboutAction = QAction("&About", self, statusTip="About GuloMail", triggered=self.about) self.cancelAction = QAction("&Cancel", self, statusTip="Cancel") def createStatusBar(self): self.statusBar() def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.sendReceiveAction) self.fileMenu.addAction(self.printAction) self.fileMenu.addAction(self.quitAction) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.copyAction) self.editMenu.addAction(self.deleteAction) self.viewMenu = self.menuBar().addMenu("&View") self.folderMenu = self.menuBar().addMenu("F&older") self.messageMenu = self.menuBar().addMenu("&Message") self.goToMenu = self.messageMenu.addMenu("&Go To") self.goToMenu.addAction(self.nextAction) self.goToMenu.addAction(self.previousAction) self.messageMenu.addAction(self.replyAction) self.messageMenu.addAction(self.replyToAllAction) self.messageMenu.addAction(self.forwardAction) self.markAsMenu = self.messageMenu.addMenu("Mar&k as...") self.markAsMenu.addAction(self.junkAction) self.markAsMenu.addAction(self.notJunkAction) self.searchMenu = self.menuBar().addMenu("&Search") self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.contentsAction) self.helpMenu.addAction(self.aboutAction) def createToolbars(self): self.toolbar = self.addToolBar('Main Toolbar') self.toolbar.setMovable(False) self.toolbar.addAction(self.newAction) self.toolbar.addSeparator() self.toolbar.addAction(self.sendReceiveAction) self.toolbar.addSeparator() self.toolbar.addAction(self.replyAction) self.toolbar.addAction(self.replyToAllAction) self.toolbar.addAction(self.forwardAction) self.toolbar.addSeparator() self.toolbar.addAction(self.printAction) self.toolbar.addAction(self.deleteAction) self.toolbar.addAction(self.junkAction) self.toolbar.addAction(self.notJunkAction) self.toolbar.addAction(self.cancelAction) self.toolbar.addSeparator() self.toolbar.addAction(self.previousAction) self.toolbar.addAction(self.nextAction) def createWidgets(self): ## Message Table self.table = QTableView() self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setGridStyle(Qt.NoPen) self.model = QStandardItemModel(8, 3, self) self.model.setHeaderData(0, Qt.Horizontal, "From") self.model.setHeaderData(1, Qt.Horizontal, "Subject") self.model.setHeaderData(2, Qt.Horizontal, "Received") self.table.setModel(self.model) self.selectionModel = QItemSelectionModel(self.model) self.selectionModel.SelectionFlag = 0x0020 self.table.setSelectionModel(self.selectionModel) self.table.horizontalHeader().setStretchLastSection(True) self.table.verticalHeader().setVisible(False) self.table.setSortingEnabled(True) self.table.setAlternatingRowColors(True) ## Folder Tree View self.folderTree = QTreeWidget() self.folderTree.setColumnCount(1) self.folderTree.setHeaderLabel(QString('Folders')) self.treeItem = QTreeWidgetItem() self.treeItem.setText(0, 'Folders') self.inbox = QTreeWidgetItem() self.inbox.setText(0, 'Inbox') self.deletedItems = QTreeWidgetItem() self.deletedItems.setText(0, 'Deleted Items') self.drafts = QTreeWidgetItem() self.drafts.setText(0, 'Drafts') self.junk = QTreeWidgetItem() self.junk.setText(0, 'Junk') self.outbox = QTreeWidgetItem() self.outbox.setText(0, 'Outbox') self.sent = QTreeWidgetItem() self.sent.setText(0, 'Sent') self.treeItem.addChild(self.inbox) self.treeItem.addChild(self.deletedItems) self.treeItem.addChild(self.drafts) self.treeItem.addChild(self.junk) self.treeItem.addChild(self.outbox) self.treeItem.addChild(self.sent) self.folderTree.addTopLevelItem(self.treeItem) self.folderTree.expandAll() self.folderTree.setAnimated(True) self.folderTree.setMaximumWidth(150) ## Temp. placeholders self.textEdit = QTextEdit() self.textEdit2 = QTextEdit() def createLayouts(self): self.mainSplitter = QSplitter() self.setCentralWidget(self.mainSplitter) self.mainSplitter.addWidget(self.folderTree) self.messageSplitter = QSplitter(Qt.Vertical) self.messageSplitter.addWidget(self.table) self.messageSplitter.addWidget(self.textEdit2) self.mainSplitter.addWidget(self.messageSplitter) def helpContents(self): print "Help" def reply(self): print "Reply" def replyToAll(self): print "Reply To All" def about(self): text = QString("GuloMail v0.1\n\n") text.append( "GuloMail is a freeware email client written in Python using PyQt4 (Python bindings for Nokia's Qt)\n\n" ) text.append(QChar(0x00A9)) text.append("GulonSoft 2010\nhttp://www.gulon.co.uk/") QMessageBox.about(self, "About GuloMail", text)