Esempio n. 1
0
class ProblemDialog(QDialog):
    def __init__(self, parent, model):
        flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
        QDialog.__init__(self, parent, flags)
        self._setupUi()
        self.model = model
        self.model.view = self
        self.table = ProblemTable(self.model.problem_table, view=self.tableView)
        
        self.revealButton.clicked.connect(self.model.reveal_selected_dupe)
        self.closeButton.clicked.connect(self.accept)
    
    def _setupUi(self):
        self.setWindowTitle(tr("Problems!"))
        self.resize(413, 323)
        self.verticalLayout = QVBoxLayout(self)
        self.label = QLabel(self)
        msg = tr("There were problems processing some (or all) of the files. The cause of "
            "these problems are described in the table below. Those files were not "
            "removed from your results.")
        self.label.setText(msg)
        self.label.setWordWrap(True)
        self.verticalLayout.addWidget(self.label)
        self.tableView = QTableView(self)
        self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableView.setShowGrid(False)
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.verticalHeader().setDefaultSectionSize(18)
        self.tableView.verticalHeader().setHighlightSections(False)
        self.verticalLayout.addWidget(self.tableView)
        self.horizontalLayout = QHBoxLayout()
        self.revealButton = QPushButton(self)
        self.revealButton.setText(tr("Reveal Selected"))
        self.horizontalLayout.addWidget(self.revealButton)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.closeButton = QPushButton(self)
        self.closeButton.setText(tr("Close"))
        self.closeButton.setDefault(True)
        self.horizontalLayout.addWidget(self.closeButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
Esempio n. 2
0
class IgnoreListDialog(QDialog):
    def __init__(self, parent, model):
        flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
        QDialog.__init__(self, parent, flags)
        self._setupUi()
        self.model = model
        self.model.view = self
        self.table = IgnoreListTable(self.model.ignore_list_table,
                                     view=self.tableView)

        self.removeSelectedButton.clicked.connect(self.model.remove_selected)
        self.clearButton.clicked.connect(self.model.clear)
        self.closeButton.clicked.connect(self.accept)

    def _setupUi(self):
        self.setWindowTitle(tr("Ignore List"))
        self.resize(540, 330)
        self.verticalLayout = QVBoxLayout(self)
        self.tableView = QTableView()
        self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableView.setShowGrid(False)
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.verticalHeader().setDefaultSectionSize(18)
        self.tableView.verticalHeader().setHighlightSections(False)
        self.tableView.verticalHeader().setVisible(False)
        self.verticalLayout.addWidget(self.tableView)
        self.removeSelectedButton = QPushButton(tr("Remove Selected"))
        self.clearButton = QPushButton(tr("Clear"))
        self.closeButton = QPushButton(tr("Close"))
        self.verticalLayout.addLayout(
            horizontalWrap([
                self.removeSelectedButton, self.clearButton, None,
                self.closeButton
            ]))

    #--- model --> view
    def show(self):
        QDialog.show(self)
class IgnoreListDialog(QDialog):
    def __init__(self, parent, model):
        flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
        QDialog.__init__(self, parent, flags)
        self._setupUi()
        self.model = model
        self.model.view = self
        self.table = IgnoreListTable(self.model.ignore_list_table, view=self.tableView)
        
        self.removeSelectedButton.clicked.connect(self.model.remove_selected)
        self.clearButton.clicked.connect(self.model.clear)
        self.closeButton.clicked.connect(self.accept)
    
    def _setupUi(self):
        self.setWindowTitle(tr("Ignore List"))
        self.resize(540, 330)
        self.verticalLayout = QVBoxLayout(self)
        self.tableView = QTableView()
        self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableView.setShowGrid(False)
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.verticalHeader().setDefaultSectionSize(18)
        self.tableView.verticalHeader().setHighlightSections(False)
        self.tableView.verticalHeader().setVisible(False)
        self.verticalLayout.addWidget(self.tableView)
        self.removeSelectedButton = QPushButton(tr("Remove Selected"))
        self.clearButton = QPushButton(tr("Clear"))
        self.closeButton = QPushButton(tr("Close"))
        self.verticalLayout.addLayout(horizontalWrap([self.removeSelectedButton, self.clearButton,
            None, self.closeButton]))
    
    #--- model --> view
    def show(self):
        QDialog.show(self)
Esempio n. 4
0
class FreezeTableWidget(QTableView):
    def __init__(self, table_data, headers, parent=None, *args):
        """
        Creates two QTableViews one of which is a frozen table while the
        other one can scroll behind it.
        :param table_data: The data that goes into the tables
        :type table_data: List
        :param headers: The header data of the tables.
        :type headers: List
        :param parent: The parent of the QTableView
        :type parent: QWidget
        :param args:
        :type args:
        """
        QTableView.__init__(self, parent)
        # set the table model
        self.table_model = BaseSTDMTableModel(table_data, headers, parent)
        # set the proxy model
        proxy_model = QSortFilterProxyModel(self)
        proxy_model.setSourceModel(self.table_model)
        # Assign a data model for TableView
        self.setModel(self.table_model)
        # frozen_table_view - first column
        self.frozen_table_view = QTableView(self)
        # Set the model for the widget, fixed column
        self.frozen_table_view.setModel(self.table_model)
        # Hide row headers
        self.frozen_table_view.verticalHeader().hide()
        # Widget does not accept focus
        self.frozen_table_view.setFocusPolicy(Qt.StrongFocus | Qt.TabFocus
                                              | Qt.ClickFocus)
        # The user can not resize columns
        self.frozen_table_view.horizontalHeader().\
            setResizeMode(QHeaderView.Fixed)
        self.frozen_table_view.setObjectName('frozen_table')
        self.setSelectionMode(QAbstractItemView.NoSelection)
        self.set_style()
        # Remove the scroll bar
        self.frozen_table_view.setHorizontalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        self.frozen_table_view.setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff)
        # Puts more widgets to the foreground
        self.viewport().stackUnder(self.frozen_table_view)
        # # Log in to edit mode - even with one click
        # Set the properties of the column headings
        hh = self.horizontalHeader()
        # Text alignment centered
        hh.setDefaultAlignment(Qt.AlignCenter)

        self.set_column_width()
        # Set properties header lines
        vh = self.verticalHeader()
        vh.setDefaultSectionSize(25)  # height lines
        # text alignment centered
        vh.setDefaultAlignment(Qt.AlignCenter)
        vh.setVisible(True)
        # Height of rows - as in the main widget
        self.frozen_table_view.verticalHeader().\
            setDefaultSectionSize(
            vh.defaultSectionSize()
        )
        # Show frozen table view
        self.frozen_table_view.show()
        # Set the size of him like the main

        self.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.frozen_table_view.setVerticalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        ## select the first column (STR Type)
        self.frozen_table_view.selectColumn(0)

        self.frozen_table_view.setEditTriggers(
            QAbstractItemView.AllEditTriggers)
        self.set_size()
        self.signals()

    def set_size(self):
        """
        Sets the size and size policy of the tables.
        :return:
        :rtype:
        """
        size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        size_policy.setHorizontalStretch(0)
        size_policy.setVerticalStretch(0)
        size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(size_policy)
        self.setMinimumSize(QSize(55, 75))
        self.setMaximumSize(QSize(5550, 5555))
        self.SelectionMode(QAbstractItemView.SelectColumns)
        # set column width to fit contents
        self.frozen_table_view.resizeColumnsToContents()
        # set row height
        self.frozen_table_view.resizeRowsToContents()

    def signals(self):
        """
        Connects signals of the tables.
        """
        # Connect the headers and scrollbars of
        # both tableviews together
        self.horizontalHeader().sectionResized.connect(
            self.update_section_width)
        self.verticalHeader().sectionResized.connect(
            self.update_section_height)
        self.frozen_table_view.verticalScrollBar(). \
            valueChanged.connect(
            self.verticalScrollBar().setValue
        )
        self.verticalScrollBar().valueChanged.connect(
            self.frozen_table_view.verticalScrollBar().setValue)

    def set_column_width(self):
        """
        Sets the column width of the frozen QTableView.
        """
        # Set the width of columns
        columns_count = self.table_model.columnCount(self)
        for col in range(columns_count):
            if col == 0:
                # Set the size
                self.horizontalHeader().resizeSection(col, 60)
                # Fix width
                self.horizontalHeader().setResizeMode(col, QHeaderView.Fixed)
                # Width of a fixed column - as in the main widget
                self.frozen_table_view.setColumnWidth(col,
                                                      self.columnWidth(col))
            elif col == 1:
                self.horizontalHeader().resizeSection(col, 150)
                self.horizontalHeader().setResizeMode(col, QHeaderView.Fixed)
                self.frozen_table_view.setColumnWidth(col,
                                                      self.columnWidth(col))
            else:
                self.horizontalHeader().resizeSection(col, 150)
                # Hide unnecessary columns in the
                # widget fixed columns
                self.frozen_table_view.setColumnHidden(col, True)

    def set_style(self):
        """
        Sets the style of the frozen table.
        """
        # Style frozentable view
        self.frozen_table_view.setStyleSheet('''
            #frozen_table{
                border-top:none;
            }
            ''')
        self.shadow = QGraphicsDropShadowEffect(self)
        self.shadow.setBlurRadius(5)
        self.shadow.setOffset(2)
        self.shadow.setYOffset(0)
        self.frozen_table_view.setGraphicsEffect(self.shadow)

    def add_widgets(self, str_type_id, insert_row):
        """
        Adds widget delete into the frozen table.
        :param str_type_id: The STR type id of the tenure type combobox
        :type str_type_id: Integer
        :param insert_row: The row number the widgets to be added.
        :type insert_row: Integer
        """
        delegate = STRTypeDelegate(str_type_id)
        # Set delegate to add combobox under
        # social tenure type column
        self.frozen_table_view.setItemDelegate(delegate)
        self.frozen_table_view.setItemDelegateForColumn(0, delegate)
        index = self.frozen_table_view.model().index(insert_row, 0,
                                                     QModelIndex())
        self.frozen_table_view.model().setData(index, '', Qt.EditRole)

        self.frozen_table_view.openPersistentEditor(
            self.frozen_table_view.model().index(insert_row, 0))
        self.frozen_table_view.openPersistentEditor(
            self.frozen_table_view.model().index(insert_row, 1))

    def update_section_width(self, logicalIndex, oldSize, newSize):
        """
        Updates frozen table column width and geometry.
        :param logicalIndex: The section's logical number
        :type logicalIndex: Integer
        :param oldSize: The old size of the section
        :type oldSize: Integer
        :param newSize: The new size of the section
        :type newSize: Integer
        """
        if logicalIndex == 0 or logicalIndex == 1:
            self.frozen_table_view.setColumnWidth(logicalIndex, newSize)
            self.update_frozen_table_geometry()

    def update_section_height(self, logicalIndex, oldSize, newSize):
        """
        Updates frozen table column height.
        :param logicalIndex: The section's logical number
        :type logicalIndex: Integer
        :param oldSize: The old size of the section
        :type oldSize: Integer
        :param newSize: The new size of the section
        :type newSize: Integer
        """
        self.frozen_table_view.setRowHeight(logicalIndex, newSize)

    def resizeEvent(self, event):
        """
        Handles the resize event of the frozen table view.
        It updates the frozen table view geometry on resize of table.
        :param event: The event
        :type event: QEvent
        """
        QTableView.resizeEvent(self, event)
        try:
            self.update_frozen_table_geometry()
        except Exception as log:
            LOGGER.debug(str(log))

    def scrollTo(self, index, hint):
        """
        Scrolls the view if necessary to ensure that the item at index is
        visible. The view will try to position the item according to the
        given hint.
        :param index: The scroll index
        :type index: QModelIndex
        :param hint: The scroll hint
        :type hint: Integer
        """
        if index.column() > 1:
            QTableView.scrollTo(self, index, hint)

    def update_frozen_table_geometry(self):
        """
        Updates the frozen table view geometry.
        """
        if self.verticalHeader().isVisible():
            self.frozen_table_view.setGeometry(
                self.verticalHeader().width() + self.frameWidth(),
                self.frameWidth(),
                self.columnWidth(0) + self.columnWidth(1),
                self.viewport().height() + self.horizontalHeader().height())
        else:
            self.frozen_table_view.setGeometry(
                self.frameWidth(), self.frameWidth(),
                self.columnWidth(0) + self.columnWidth(1),
                self.viewport().height() + self.horizontalHeader().height())

    def move_cursor(self, cursor_action, modifiers):
        """
        Override function for correct left to scroll the keyboard.
        Returns a QModelIndex object pointing to the next object in the
        table view, based on the given cursorAction and keyboard modifiers
        specified by modifiers.
        :param cursor_action: The cursor action
        :type cursor_action: Integer
        :param modifiers: Qt.KeyboardModifier value.
        :type modifiers: Object
        :return: The current cursor position.
        :rtype: QModelIndex
        """
        current = QTableView.move_cursor(self, cursor_action, modifiers)
        if cursor_action == self.MoveLeft and current.column() > 1 and \
                        self.visualRect(current).topLeft().x() < \
                        (self.frozen_table_view.columnWidth(0) +
                             self.frozen_table_view.columnWidth(1)):
            new_value = self.horizontalScrollBar().value() + \
                       self.visualRect(current).topLeft().x() - \
                       (self.frozen_table_view.columnWidth(0) +
                        self.frozen_table_view.columnWidth(1))
            self.horizontalScrollBar().setValue(new_value)
        return current
Esempio n. 5
0
class I4CheckWindow(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setup_model()

        self.tableview = QTableView()
        self.tableview.setSelectionMode(QAbstractItemView.NoSelection)
        self.tableview.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.cbdelegate = CheckBoxDelegate()
        self.tableview.setItemDelegate(self.cbdelegate)
        self.tableview.setAutoScroll(False)
        self.tableview.setModel(self.model)
        self.tableview.sortByColumn(0, Qt.AscendingOrder)
        self.adjust_headers()

        #self.model.setHeaderData(0, Qt.Horizontal, u"")
        #self.model.setHeaderData(1, Qt.Horizontal, u"Title")

        self.radio_all = QRadioButton("All")
        self.radio_all.setChecked(True)
        self.radio_need = QRadioButton("Need")
        self.connect(self.radio_all, SIGNAL("toggled(bool)"), self.set_show_all)

        label = QLabel("DB:")
        label.setFixedWidth(40)
        label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

        self.db_combo = QComboBox()
        self.populate_db_combo()
        self.connect(
            self.db_combo, SIGNAL("currentIndexChanged(int)"),
            self.db_index_changed)

        self.new_button = QPushButton("New")
        self.connect(self.new_button, SIGNAL("clicked()"), self.new_item)

        self.box = QVBoxLayout(self)
        self.box.addWidget(self.tableview)
        self.button_box = QHBoxLayout()
        self.button_box.setSpacing(0)
        self.button_box.addWidget(self.new_button)
        self.button_box.addWidget(self.radio_all)
        self.button_box.addWidget(self.radio_need)
        self.button_box.addWidget(label)
        self.button_box.addWidget(self.db_combo)
        self.box.addLayout(self.button_box)

        # self.setStyleSheet("""
        # QComboBox {
        #     font-size: 16px;
        # }
        # """)

        self.dwim_after_load()

    def dwim_after_load(self):
        if self.model.need_anything():
            self.radio_need.setChecked(True)
            return
        self.radio_all.setChecked(True)
        if self.model.model.rowCount() == 0:
            edit_index = self.model.new()
            self.tableview.setCurrentIndex(edit_index)
            self.tableview.scrollTo(edit_index)
            self.tableview.edit(edit_index)

    def adjust_headers(self):
        log.debug("adjust_sizes()")
        self.tableview.horizontalHeader().setResizeMode(0, QHeaderView.Stretch)
        self.tableview.setColumnWidth(0, 1)
        self.tableview.verticalHeader().setDefaultSectionSize(ITEM_HEIGHT)
        self.tableview.verticalHeader().hide()
        self.tableview.horizontalHeader().hide()

    def setup_model(self):
        self.model = CheckListModel()

    def new_item(self):
        index = self.model.new()
        self.tableview.setCurrentIndex(index)
        self.tableview.resizeRowToContents(index.row())
        self.tableview.scrollTo(index)
        self.tableview.edit(index)

    def set_show_all(self, show_all):
        if self.model.show_all == show_all:
            return
        self.model.set_show_all(show_all)
        self.tableview.resizeRowsToContents()

    def save(self):
        self.model.save()

    def checkout(self):
        if QMessageBox.question(
            self, "Checkout", "Are you sure you want to check out?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == \
            QMessageBox.Yes:
            self.model.checkout()

    def reset_items(self):
        if QMessageBox.question(
            self, "Checkout", "Are you sure you want to reset the list?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == \
            QMessageBox.Yes:
            self.model.reset_items()
            self.radio_all.setChecked(True)

    def delete_database(self):
        if QMessageBox.question(
            self, "Delete database",
            "Are you sure you want to delete the current database?",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == \
            QMessageBox.Yes:
            self.model.delete_database()
            self.populate_db_combo()
            self.dwim_after_load()

    _loading_db_combo = False

    def populate_db_combo(self):
        self._loading_db_combo = True
        try:
            self.db_combo.clear()
            for db_name in self.model.databases:
                self.db_combo.addItem(re.sub("\\.org$", "", db_name), db_name)
            self.db_combo.addItem("New database...", "")
            self.db_combo.setCurrentIndex(
                self.model.databases.index(self.model.current_db))
        finally:
            self._loading_db_combo = False

    def db_index_changed(self, index):
        if self._loading_db_combo:
            return
        db_name = str(self.db_combo.itemData(index).toPyObject())
        if db_name == self.model.current_db:
            return

        self.model.save()

        if db_name:
            self.model.load(db_name)
            self.dwim_after_load()
            return

        db_name, ok = QInputDialog.getText(
            self, "New Database", "Enter database name")
        if ok:
            if not re.match(r"^[\w-]+$", db_name):
                QMessageBox.critical(
                    self, "Error",
                    "Database name must contain only the following chars: "
                    "A-Z a-z 0-9 _ -")
                ok = False
            elif db_name in self.model.databases:
                QMessageBox.critical(
                    self, "Error", "Database '%s' already exists" % db_name)
                ok = False
        if not ok:
            self.db_combo.setCurrentIndex(
                self.model.databases.index(self.model.current_db))
            return
        db_name = str(db_name) + ".org"
        self.model.load(db_name)
        self.populate_db_combo()
        self.dwim_after_load()
Esempio n. 6
0
class Emotion(QtGui.QWidget):
    EMOTION_DIR = "./resource/expression"
    WIDTH = 460
    HEIGHT = 300
    selectChanged = pyqtSignal(str)
    
    def __init__(self,parent=None):#
        super(Emotion,self).__init__(parent)
        super(Emotion,self).setWindowFlags(QtCore.Qt.Popup)
        self.resize(QSize(Emotion.WIDTH,Emotion.HEIGHT))
        self.setWindowTitle("表情選擇")
        #self.setModal(True)
        #self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        self.emotion_initial()
        
    def emotion_initial(self):
        self.emotion_table = QTableView()
        self.emotion_table.horizontalHeader().setVisible(False)
        self.emotion_table.verticalHeader().setVisible(False)
        self.emotion_table.setMouseTracking(True)
        self.emotion_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.emotion_table.verticalHeader().setDefaultSectionSize(30)
        self.emotion_table.horizontalHeader().setDefaultSectionSize(30)
        self.emotion_table.setIconSize(QSize(30,30))
        self.emotion_table.entered.connect(self.showEmotionTips)
        self.emotion_model = QStandardItemModel()
        
        emotions = os.listdir(Emotion.EMOTION_DIR)
        i = 0
        emotions_size = len(emotions)
        emotions = sorted(emotions,cmp=emotioncmp)
        while i < emotions_size:
            self.add_emotion(emotions[i:i+14])
            i = i + 14
        self.emotion_table.setModel(self.emotion_model)
        self.emotion_table.clicked.connect(self.emotion_click) 
        #
        mainLayout=QVBoxLayout()
        mainLayout.addWidget(self.emotion_table)
        self.setLayout(mainLayout)
        #self.
    def showEmotionTips(self,index):
        if index.isValid():
            QToolTip.showText(QCursor.pos(), "Hello", None)
    
    def add_emotion(self,emotions):
        '''
        :param emotions a list of emotion will be adding to emotion table
        '''
        cells = []
        for emotion in emotions:
            item = QtGui.QStandardItem(QIcon(os.path.join(Emotion.EMOTION_DIR,emotion)),emotion)
            cells.append(item)
        self.emotion_model.appendRow(cells)

    #def eventFilter(self, event):
        #p = QCursor.pos() - self.pos()
        #item = self.emotion_table
        
    def emotion_click(self):
        row = self.emotion_table.currentIndex().row()
        column = self.emotion_table.currentIndex().column()
        #self.accept()
        self.close()
        self.selectChanged.emit(self.get_selected_emotion(row,column))
        
    def get_selected_emotion(self,row,column):
        emotion = self.emotion_model.data(self.emotion_model.index(row, column))
        if emotion:
            return str(emotion.toString())
        else:
            return "N/A"
Esempio n. 7
0
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)
Esempio n. 8
0
class ThemeConfigurationWidget(QWidget):
    """Themes are stored in directory 'themes' in configuration directory. Each theme file has .mixth extension
    and represents single theme.
    """

    def __init__(self, parent):
        QWidget.__init__(self, parent)

        self.cmbThemes = QComboBox(self)
        self.cmbThemes.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        self.cmbThemes.currentIndexChanged[int].connect(self._changeCurrentTheme)

        self.btnCopyTheme = QPushButton(self)
        self.btnCopyTheme.setText(utils.tr('Copy theme...'))
        self.btnCopyTheme.clicked.connect(self._copyTheme)

        self.componentsView = QTableView(self)
        self.themeModel = ThemeModel()
        self.componentsView.setModel(self.themeModel)
        self.componentsView.setSelectionBehavior(QTableView.SelectRows)
        self.componentsView.setItemDelegateForColumn(1, ComponentDelegate())
        self.componentsView.setEditTriggers(QTableView.DoubleClicked)

        self.setLayout(QVBoxLayout())
        h_layout = QHBoxLayout()
        h_layout.addWidget(self.cmbThemes)
        h_layout.addWidget(self.btnCopyTheme)
        self.layout().addLayout(h_layout)
        self.layout().addWidget(self.componentsView)

    def resizeEvent(self, event):
        view_size = self.componentsView.size()
        hh = self.componentsView.horizontalHeader()
        hh.resizeSection(0, int((view_size.width() - self.componentsView.verticalHeader().width()) * 0.6))
        hh.setStretchLastSection(True)

    def loadThemes(self, theme_to_select=None):
        if theme_to_select is None:
            theme_to_select = globalSettings[appsettings.HexWidget_Theme]

        self.cmbThemes.clear()
        self.cmbThemes.addItem(utils.tr('Default (unmodifiable)'), '')
        if not theme_to_select:
            self.cmbThemes.setCurrentIndex(0)
        for theme_name in hexwidget.Theme.availableThemes():
            self.cmbThemes.addItem(theme_name.capitalize(), theme_name)
            if theme_name == theme_to_select:
                self.cmbThemes.setCurrentIndex(self.cmbThemes.count() - 1)

    def saveCurrentTheme(self):
        if self.themeModel.theme is not None and self.themeName:
            theme_name = self.themeName
            self.themeModel.theme.save(theme_name)
            self.loadThemes(theme_name)

    @property
    def themeName(self):
        return self.cmbThemes.itemData(self.cmbThemes.currentIndex())

    def _copyTheme(self):
        while True:
            theme_name, ok = QInputDialog.getText(self, utils.tr('Copy theme'), utils.tr('Name for copy of theme:'))
            if not ok:
                break
            if (not theme_name or hexwidget.Theme.themeFromName(theme_name) is not None or not utils.isValidFilename(theme_name)):
                QMessageBox.information(self, utils.tr('Wrong name for theme'), utils.tr('Name for theme is invalid'))
            else:
                break

        if ok:
            self.themeModel.theme.save(theme_name)
            self.loadThemes(theme_name)

    def _changeCurrentTheme(self, index):
        if self.themeName and self.themeModel.modified:
            if QMessageBox.question(self, utils.tr('Save theme'),
                                    utils.tr('Do you want to save "{0}"?').format(self.themeName),
                                    QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) == QMessageBox.Yes:
                self.themeModel.theme.save()

        theme_name = self.cmbThemes.itemData(index)
        if index >= 0 and theme_name is not None:
            theme = hexwidget.Theme.themeFromName(theme_name) or hexwidget.Theme()
        else:
            theme = None
        self.themeModel.theme = theme
Esempio n. 9
0
class MainWindow(QMainWindow):
    """
        Initialization
    """
    def __init__(self, rulesModel, logoFnam, *args):
        QMainWindow.__init__(self, *args)
        
        self.rulesModel = rulesModel
        
        self.rulesModel.dataChanged.connect(self._statusRefresh)
        
        self.cancelled = True   # for to handle win close box the same as Cancel button
        
        self.mainHSplit = QSplitter(self)   # data | buttons
        self.mainHSplit.setChildrenCollapsible(False)
        self.setCentralWidget(self.mainHSplit)

        self.mainVSplit = QSplitter(Qt.Vertical)
        self.mainVSplit.setChildrenCollapsible(False)
        self.mainHSplit.addWidget(self.mainVSplit)
        
        self._drawRules()
        self.mainVSplit.addWidget(self.rulesView)
        self.condActSplit = QSplitter()
        self.condActSplit.setChildrenCollapsible(False)
        self._drawCondAct()
        self.mainVSplit.addWidget(self.condActSplit)
        # let rules view resize vertically two times faster than cond/action view
        self.rulesView.setSizeIncrement(self.rulesView.sizeIncrement().width(), 
                                        2 * self.condView.sizeIncrement().height())
        
        self._drawButtons(logoFnam)
        self.setStatusBar(QStatusBar())
        self.condView.horizontalHeader().setCascadingSectionResizes(True)
        self.rulesView.selectRow(0)
                                
    def _drawRules(self):
        self.rulesView = QTableView()
        self.rulesView.setModel(self.rulesModel)
        self.rulesView.setEditTriggers(QAbstractItemView.AllEditTriggers)
        self.rulesView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.rulesView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.rulesView.horizontalHeader().setStretchLastSection(True)
        self.rulesView.resizeColumnsToContents()
        #self.rulesView.verticalHeader().setMovable(True)  # row remapping - see QHeaderView.logicalIndex()
        #self.rulesView.verticalHeader().setCascadingSectionResizes(True)  # takes space from next row
        self.rulesView.selectionModel().currentRowChanged.connect(self._ruleRowChanged)
        self.rulesView.verticalHeader().sectionResized[int,int,int].connect(self._ruleRowHeightChanged)
        
    def _drawCondAct(self):
        if getattr(self, 'condGB', None):
            m_settings.setValue('spl_condAct', self.condActSplit.saveState())
            self.condGB.deleteLater() # or .destroy()
            del self.condGB
            self.actionGB.deleteLater()
            del self.actionGB
            
        row = self._ruleCurrRow()
        rcount = self.rulesModel.rowCount()
        
        self.condGB = QGroupBox(self.tr('Conditions'))
        self.condView = QTableView()
        conds = self.rulesModel.ruleConditions(row) if row in range(rcount) \
                else []
        self.condModel = ConditionsModel(conds, self.rulesModel)
        self.condModel.dataChanged.connect(self._codeFragChanged)
        self.condView.setModel(self.condModel)
        self.condTypeDelegate = ComboBoxDelegate(Condition._types._typeCaptions)
        self.condView.setItemDelegateForColumn(0, self.condTypeDelegate)
        self.condView.setEditTriggers(QAbstractItemView.AllEditTriggers)
        self.condView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.condView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.condView.horizontalHeader().setStretchLastSection(True)
        self.condView.resizeColumnsToContents()
        self.condView.selectionModel().currentRowChanged.connect(self._statusRefresh)
        vbox = QVBoxLayout()
        vbox.addWidget(self.condView)
        self.condGB.setLayout(vbox)
        self.condActSplit.addWidget(self.condGB)
        
        self.actionGB = QGroupBox(self.tr('Actions'))
        self.actionView = QTableView()   # parent = self.actionGB)
        actions = self.rulesModel.ruleActions(row) if row in range(rcount) \
                else []
        self.actionModel = ActionsModel(actions, self.rulesModel)
        self.actionModel.dataChanged.connect(self._codeFragChanged)
        self.actionView.setModel(self.actionModel)
        self.actionTypeDelegate = ComboBoxDelegate(Action._types._typeCaptions)
        self.actionView.setItemDelegateForColumn(0, self.actionTypeDelegate)
        self.actionView.setEditTriggers(QAbstractItemView.AllEditTriggers)
        self.actionView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.actionView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.actionView.horizontalHeader().setStretchLastSection(True)
        self.actionView.resizeColumnsToContents()
        self.actionView.selectionModel().currentRowChanged.connect(self._statusRefresh)
        vbox = QVBoxLayout()
        vbox.addWidget(self.actionView)
        self.actionGB.setLayout(vbox)
        self.condActSplit.addWidget(self.actionGB)
        
        self.condActSplit.restoreState(m_settings.value('spl_condAct').toByteArray())

        
    def _drawButton(self, vbox, caption, slot, ena = False):
        but = QPushButton(self.tr(caption))
        but.setEnabled(ena)
        but.clicked.connect(getattr(self, slot))
        vbox.addWidget(but)     # add to VBoxLayout
        return but
    
    def _drawButtons(self, logoFnam):
        gbox = QGroupBox()
        spol = QSizePolicy()
        spol.horizontalPolicy = QSizePolicy.Maximum
        gbox.setSizePolicy(spol)
        vbox = QVBoxLayout()
        
        if os.path.isfile(logoFnam):
            img = QPixmap(logoFnam)    #.scaled(64, 64)
            lblLogo = QLabel()
            lblLogo.setPixmap(img)
            lblLogo.setAlignment(Qt.AlignTop | Qt.AlignRight)
            vbox.addWidget(lblLogo)
            #vbox.addSpacing(3) 
        
        self.butSave = self._drawButton(vbox, "M&odify", 'closeSave')
        font = QFont()
        font.setBold(True)
        self.butSave.setFont(font)
        self.butCancel = self._drawButton(vbox, "Cancel", 'closeCancel', True)
        vbox.addSpacing(36)
        self.butAddRule = self._drawButton(vbox, "Add Rule", 'addRule', True)
        self.butCopyRule = self._drawButton(vbox, "Copy Rule", 'copyRule')
        self.butDelRule = self._drawButton(vbox, "Delete Rule", 'delRule')
        self.butMoveRuleUp = self._drawButton(vbox, "Move Rule Up", 'moveRuleUp')
        self.butMoveRuleDn = self._drawButton(vbox, "Move Rule Down", 'moveRuleDown')
        vbox.addSpacing(24)
        self.butAddCond = self._drawButton(vbox, "Add Condition", 'addCond')
        self.butDelCond = self._drawButton(vbox, "Delete Condition", 'delCond')
        vbox.addSpacing(15)
        self.butAddAction = self._drawButton(vbox, "Add Action", 'addAction')
        self.butDelAction = self._drawButton(vbox, "Delete Action", 'delAction')
        
        gbox.setLayout(vbox)
        self.mainHSplit.addWidget(gbox) 
    
    """
        Internal Bindings Signal Receivers
    """
    # main win close events
    # .. (cancel closing with event.ignore(); QMainWindow calls event.accept())       
    @pyqtSlot(QCloseEvent)
    def closeEvent(self, event):
        self._saveAppState()
        # save rules if not empty and user clicked Modified/Save button
        if self.rulesModel.rowCount() > 0 and not self.cancelled:
            text = self.rulesModel.getRawRules().validate()
            if text:
                self.cancelled = True
                QMessageBox.information(self, APP_TITLE, 
                                        self.tr("Validation failed because of:<p><p>") + text)
                event.ignore()
                return              #  RETURN - cancel app closing ######
            self.rulesModel.saveScript()
        # accept window closing
        QMainWindow.closeEvent(self, event)
        # quit application
        m_app.quit()
    @pyqtSlot()
    def _statusRefresh(self):       # dis/enable buttons, display view selections
        ruleRow = self._ruleCurrRow()
        condRow = self._condCurrRow()
        actionRow = self._actionCurrRow()
        self.butSave.setEnabled(self.rulesModel.isModified())
        ruleCnt = self.rulesModel.rowCount()
        self.butCopyRule.setEnabled(ruleRow >= 0)
        self.butDelRule.setEnabled(ruleRow >= 0)
        self.butMoveRuleUp.setEnabled(ruleRow > 0)
        self.butMoveRuleDn.setEnabled(ruleRow >= 0 and ruleRow + 1 < ruleCnt)
        self.butAddCond.setEnabled(ruleRow >= 0)
        self.butDelCond.setEnabled(condRow >= 0)  
        self.butAddAction.setEnabled(ruleRow >= 0)
        self.butDelAction.setEnabled(actionRow >= 0)
        # display currently selected list rows in the status bar - if empty
        if ruleRow >= 0 and False:    # replace False with ~self.statusBar().isEmpty()?!?!?
            text = str(self.tr("Selected Rule: {ruleI}"))\
                .format(ruleI = ruleRow + 1)
            if condRow >= 0:
                text += "      " \
                    + str(self.tr("Selected Condition: {typeI}"))\
                    .format(typeI = condRow + 1)
            if actionRow >= 0:
                text += "      " \
                    + str(self.tr("Selected Action: {typeI}"))\
                    .format(typeI = actionRow + 1)
            self.statusBar().showMessage(text, 3000)
    @pyqtSlot(int,int,int)
    def _ruleRowHeightChanged(self, section, oldsize, newsize):
        hdr = self.rulesView.verticalHeader()
        for row in range(hdr.count()):
            if row != section:
                hdr.resizeSection(row, newsize)
    @pyqtSlot()
    def _ruleRowChanged(self):
        self._drawCondAct()
        self._statusRefresh()
    @pyqtSlot()
    def _codeFragChanged(self):     # refresh the rules list columns Conditions and Actions
        row = self._ruleCurrRow()
        leftColIndex = self.rulesModel.index(row, 2, QModelIndex())
        rightColIndex = self.rulesModel.index(row, 3, QModelIndex())
        self.rulesView.dataChanged(leftColIndex, rightColIndex)
        self._statusRefresh()
        
    """
        User Action Signal Receivers
    """
    @pyqtSlot()
    def closeSave(self):
        self.cancelled = False
        self.close()
    @pyqtSlot()
    def closeCancel(self):
        self.cancelled = True
        self.close()
    @pyqtSlot()
    def addRule(self):
        row = self._ruleCurrRow()
        self.rulesModel.insertRow(row)
        self.rulesView.selectRow(row)
        self._statusRefresh()
    @pyqtSlot()
    def copyRule(self):
        row = self._ruleCurrRow()
        self.rulesModel.setSourceRowForNextAdd(row)
        self.rulesModel.insertRow(row)
        self.rulesView.selectRow(row)
        self._statusRefresh()
    @pyqtSlot()
    def delRule(self):
        self.rulesModel.removeRow(self._ruleCurrRow())
        self._statusRefresh()
    @pyqtSlot()
    def moveRuleUp(self):
        row = self._ruleCurrRow()
        self.rulesModel.moveRule(row, -1)
        self._statusRefresh()
    @pyqtSlot()
    def moveRuleDown(self):
        row = self._ruleCurrRow()
        self.rulesModel.moveRule(row)
        self._statusRefresh()
    @pyqtSlot()
    def addCond(self):
        cnt = self.condModel.rowCount()
        self.condModel.insertRow(cnt)
        self.condView.selectRow(cnt)
        self._statusRefresh()
    @pyqtSlot()
    def delCond(self):
        self.condModel.removeRow(self._condCurrRow())
        self._statusRefresh()
    @pyqtSlot()
    def addAction(self):
        cnt = self.actionModel.rowCount()
        self.actionModel.insertRow(cnt)
        self.actionView.selectRow(cnt)
        self._statusRefresh()
    @pyqtSlot()
    def delAction(self):
        self.actionModel.removeRow(self._actionCurrRow())
        self._statusRefresh()
    
    """
        Helping Methods
    """
    def _ruleCurrRow(self):
        #idxs = self.rulesView.selectedIndexes()
        #return idxs[0].row() if idxs else -1
        return self.rulesView.currentIndex().row()
    def _condCurrRow(self):
        return self.condView.currentIndex().row()
    def _actionCurrRow(self):
        return self.actionView.currentIndex().row()
    
    # main win save/restore
    def _saveAppState(self):
        m_app.processEvents()
        # save win geometry and splitter positions
        _UI_SAVE(self, 'win_geometry')
        _UI_SAVE(self.mainHSplit, 'spl_mainH')
        _UI_SAVE(self.mainVSplit, 'spl_mainV')
        _UI_SAVE(self.condActSplit, 'spl_condAct')
        #_UI_SAVE(self.condView.horizontalHeader(), 'tvh_condHdr')
    def _restoreAppState(self):
        try:    # will fail on first app startup after installation
            # restore last win position, -size and 3 splitter positions
            _UI_RESTORE(self, 'win_geometry')
            _UI_RESTORE(self.mainHSplit, 'spl_mainH')
            _UI_RESTORE(self.mainVSplit, 'spl_mainV')
            _UI_RESTORE(self.condActSplit, 'spl_condAct')
            #_UI_RESTORE(self.condView.horizontalHeader(), 'tvh_condHdr')
        except: # first start
            screenWidth = QApplication.desktop().width()
            screenHeight = QApplication.desktop().height()
            self.setGeometry(screenWidth / 9, screenHeight / 12,
                            screenWidth / 1.26, screenHeight / 1.56)
Esempio n. 10
0
class FreezeTableWidget(QTableView):

    def __init__(
            self, table_data, headers, parent = None, *args
    ):
        """
        Creates two QTableViews one of which is a frozen table while the
        other one can scroll behind it.
        :param table_data: The data that goes into the tables
        :type table_data: List
        :param headers: The header data of the tables.
        :type headers: List
        :param parent: The parent of the QTableView
        :type parent: QWidget
        :param args:
        :type args:
        """
        QTableView.__init__(self, parent)
        # set the table model
        self.table_model = BaseSTDMTableModel(
            table_data, headers, parent
        )
        # set the proxy model
        proxy_model = QSortFilterProxyModel(self)
        proxy_model.setSourceModel(self.table_model)
        # Assign a data model for TableView
        self.setModel(self.table_model)
        # frozen_table_view - first column
        self.frozen_table_view = QTableView(self)
        # Set the model for the widget, fixed column
        self.frozen_table_view.setModel(self.table_model)
        # Hide row headers
        self.frozen_table_view.verticalHeader().hide()
        # Widget does not accept focus
        self.frozen_table_view.setFocusPolicy(
            Qt.StrongFocus|Qt.TabFocus|Qt.ClickFocus
        )
        # The user can not resize columns
        self.frozen_table_view.horizontalHeader().\
            setResizeMode(QHeaderView.Fixed)
        self.frozen_table_view.setObjectName('frozen_table')
        self.setSelectionMode(QAbstractItemView.NoSelection)
        # Remove the scroll bar
        self.frozen_table_view.setHorizontalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff
        )
        self.frozen_table_view.setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff
        )
        # Puts more widgets to the foreground
        self.viewport().stackUnder(self.frozen_table_view)
        # # Log in to edit mode - even with one click
        # Set the properties of the column headings
        hh = self.horizontalHeader()
        # Text alignment centered
        hh.setDefaultAlignment(Qt.AlignCenter)

        self.set_column_width()
        # Set properties header lines
        vh = self.verticalHeader()
        vh.setDefaultSectionSize(25) # height lines
        # text alignment centered
        vh.setDefaultAlignment(Qt.AlignCenter)
        vh.setVisible(True)
        # Height of rows - as in the main widget
        self.frozen_table_view.verticalHeader().\
            setDefaultSectionSize(
            vh.defaultSectionSize()
        )
        # Show frozen table view
        self.frozen_table_view.show()
        # Set the size of him like the main

        self.setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel
        )
        self.setVerticalScrollMode(
            QAbstractItemView.ScrollPerPixel
        )
        self.frozen_table_view.setVerticalScrollMode(
            QAbstractItemView.ScrollPerPixel
        )
        ## select the first column (STR Type)
        self.frozen_table_view.selectColumn(0)

        self.frozen_table_view.setEditTriggers(
            QAbstractItemView.AllEditTriggers
        )
        self.set_size()
        self.signals()

    def set_size(self):
        """
        Sets the size and size policy of the tables.
        :return:
        :rtype:
        """
        size_policy = QSizePolicy(
            QSizePolicy.Fixed, QSizePolicy.Fixed
        )
        size_policy.setHorizontalStretch(0)
        size_policy.setVerticalStretch(0)
        size_policy.setHeightForWidth(
            self.sizePolicy().hasHeightForWidth()
        )
        self.setSizePolicy(size_policy)
        self.setMinimumSize(QSize(55, 75))
        self.setMaximumSize(QSize(5550, 5555))
        self.SelectionMode(
            QAbstractItemView.SelectColumns
        )
        # set column width to fit contents
        self.frozen_table_view.resizeColumnsToContents()
        # set row height
        self.frozen_table_view.resizeRowsToContents()

    def signals(self):
        """
        Connects signals of the tables.
        """
        # Connect the headers and scrollbars of
        # both tableviews together
        self.horizontalHeader().sectionResized.connect(
            self.update_section_width
        )
        self.verticalHeader().sectionResized.connect(
            self.update_section_height
        )
        self.frozen_table_view.verticalScrollBar().valueChanged.connect(
            self.verticalScrollBar().setValue
        )
        self.verticalScrollBar().valueChanged.connect(
            self.frozen_table_view.verticalScrollBar().setValue
        )

    def set_column_width(self):
        """
        Sets the column width of the frozen QTableView.
        """
        # Set the width of columns
        columns_count = self.table_model.columnCount(self)
        for col in range(columns_count):
            if col == 0:
                # Set the size
                self.horizontalHeader().resizeSection(
                    col, 60
                )
                # Fix width
                self.horizontalHeader().setResizeMode(
                    col, QHeaderView.Fixed
                )
                # Width of a fixed column - as in the main widget
                self.frozen_table_view.setColumnWidth(
                    col, self.columnWidth(col)
                )
            elif col == 1:
                self.horizontalHeader().resizeSection(
                    col, 150
                )
                self.horizontalHeader().setResizeMode(
                    col, QHeaderView.Fixed
                )
                self.frozen_table_view.setColumnWidth(
                    col, self.columnWidth(col)
                )
            else:
                self.horizontalHeader().resizeSection(
                    col, 150
                )
                # Hide unnecessary columns in the
                # widget fixed columns
                self.frozen_table_view.setColumnHidden(
                    col, True
                )

    def add_widgets(self, spatial_unit, insert_row):
        """
        Adds widget into the frozen table.
        :param str_type_id: The STR type id of the tenure type combobox
        :type str_type_id: Integer
        :param insert_row: The row number the widgets to be added.
        :type insert_row: Integer
        """
        delegate = STRTypeDelegate(spatial_unit)
        # Set delegate to add combobox under
        # social tenure type column
        self.frozen_table_view.setItemDelegate(
            delegate
        )
        self.frozen_table_view.setItemDelegateForColumn(
            0, delegate
        )
        index = self.frozen_table_view.model().index(
            insert_row, 0, QModelIndex()
        )
        self.frozen_table_view.model().setData(
            index, '', Qt.EditRole
        )

        self.frozen_table_view.openPersistentEditor(
            self.frozen_table_view.model().index(insert_row, 0)
        )
        self.frozen_table_view.openPersistentEditor(
            self.frozen_table_view.model().index(insert_row, 1)
        )

    def update_section_width(
            self, logicalIndex, oldSize, newSize
    ):
        """
        Updates frozen table column width and geometry.
        :param logicalIndex: The section's logical number
        :type logicalIndex: Integer
        :param oldSize: The old size of the section
        :type oldSize: Integer
        :param newSize: The new size of the section
        :type newSize: Integer
        """
        if logicalIndex==0 or logicalIndex==1:
            self.frozen_table_view.setColumnWidth(
                logicalIndex, newSize
            )
            self.update_frozen_table_geometry()

    def update_section_height(
            self, logicalIndex, oldSize, newSize
    ):
        """
        Updates frozen table column height.
        :param logicalIndex: The section's logical number
        :type logicalIndex: Integer
        :param oldSize: The old size of the section
        :type oldSize: Integer
        :param newSize: The new size of the section
        :type newSize: Integer
        """
        self.frozen_table_view.setRowHeight(
            logicalIndex, newSize
        )

    def resizeEvent(self, event):
        """
        Handles the resize event of the frozen table view.
        It updates the frozen table view geometry on resize of table.
        :param event: The event
        :type event: QEvent
        """
        QTableView.resizeEvent(self, event)
        try:
            self.update_frozen_table_geometry()
        except Exception as log:
            LOGGER.debug(str(log))

    def scrollTo(self, index, hint):
        """
        Scrolls the view if necessary to ensure that the item at index is
        visible. The view will try to position the item according to the
        given hint.
        :param index: The scroll index
        :type index: QModelIndex
        :param hint: The scroll hint
        :type hint: Integer
        """
        if index.column() > 1:
            QTableView.scrollTo(self, index, hint)

    def update_frozen_table_geometry(self):
        """
        Updates the frozen table view geometry.
        """
        if self.verticalHeader().isVisible():
            self.frozen_table_view.setGeometry(
                self.verticalHeader().width() +
                self.frameWidth(),
                self.frameWidth(),
                self.columnWidth(0) + self.columnWidth(1),
                self.viewport().height() +
                self.horizontalHeader().height()
            )
        else:
            self.frozen_table_view.setGeometry(
                self.frameWidth(),
                self.frameWidth(),
                self.columnWidth(0) + self.columnWidth(1),
                self.viewport().height() +
                self.horizontalHeader().height()
            )

    def move_cursor(self, cursor_action, modifiers):
        """
        Override function for correct left to scroll the keyboard.
        Returns a QModelIndex object pointing to the next object in the
        table view, based on the given cursorAction and keyboard modifiers
        specified by modifiers.
        :param cursor_action: The cursor action
        :type cursor_action: Integer
        :param modifiers: Qt.KeyboardModifier value.
        :type modifiers: Object
        :return: The current cursor position.
        :rtype: QModelIndex
        """
        current = QTableView.move_cursor(
            self, cursor_action, modifiers
        )
        if cursor_action == self.MoveLeft and current.column() > 1 and \
                        self.visualRect(current).topLeft().x() < \
                        (self.frozen_table_view.columnWidth(0) +
                             self.frozen_table_view.columnWidth(1)):
            new_value = self.horizontalScrollBar().value() + \
                       self.visualRect(current).topLeft().x() - \
                       (self.frozen_table_view.columnWidth(0) +
                        self.frozen_table_view.columnWidth(1))
            self.horizontalScrollBar().setValue(new_value)
        return current
Esempio n. 11
0
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)