예제 #1
0
    def setupTabs(self):
        """ Setup the various tabs in the AddressWidget. """
        groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"]

        for group in groups:
            proxyModel = QSortFilterProxyModel(self)
            proxyModel.setSourceModel(self.tableModel)
            proxyModel.setDynamicSortFilter(True)

            tableView = QTableView()
            tableView.setModel(proxyModel)
            tableView.setSortingEnabled(True)
            tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
            tableView.horizontalHeader().setStretchLastSection(True)
            tableView.verticalHeader().hide()
            tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            tableView.setSelectionMode(QAbstractItemView.SingleSelection)

            # This here be the magic: we use the group name (e.g. "ABC") to
            # build the regex for the QSortFilterProxyModel for the group's
            # tab. The regex will end up looking like "^[ABC].*", only
            # allowing this tab to display items where the name starts with
            # "A", "B", or "C". Notice that we set it to be case-insensitive.
            reFilter = "^[%s].*" % group

            proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive))
            proxyModel.setFilterKeyColumn(0)  # Filter on the "name" column
            proxyModel.sort(0, Qt.AscendingOrder)

            #tableView.selectionModel().selectionChanged.connect(self.selectionChanged)

            self.addTab(tableView, group)
예제 #2
0
class MainWindow(QWidget):
    
    def __init__(self):
        QWidget.__init__(self)
        self.resize(640, 480)
        vbox = QVBoxLayout()
        self.setWindowTitle('TableDemo')
        self.setLayout(vbox)
        self.table = QTableView()
        self.table.setAlternatingRowColors(True)
        self.table.setSortingEnabled(True)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        cards = [Card(u'巫医', u'战吼:恢复2点生命值。', 1, 2, 1), 
                 Card(u'狼骑兵', u'冲锋', 3, 3, 1),
                 Card(u'石牙野猪', u'冲锋', 1, 1, 1),
                 Card(u'森金持盾卫士', u'嘲讽', 4, 3, 5),
                ]
        cardModel = CardModel(cards)
        sortModel = QSortFilterProxyModel()
        sortModel.setSourceModel(cardModel)
        self.table.setModel(sortModel)
        vbox.addWidget(self.table)
        
    def printItem(self, idx):
        print idx.model().persons[idx.row()]
 def __init__(self):
     super(PhoneFrame, self).__init__()
     self.setWindowTitle('Phone Book.')
     self.name = QLineEdit()
     self.number = QLineEdit()
     entry = QFormLayout()
     entry.addRow(QLabel('Name'), self.name)
     entry.addRow(QLabel('Number'), self.number)
     buttons = QHBoxLayout()
     button = QPushButton('&Add')
     button.clicked.connect(self._addEntry)
     buttons.addWidget(button)
     button = QPushButton('&Update')
     button.clicked.connect(self._updateEntry)
     buttons.addWidget(button)
     button = QPushButton('&Delete')
     button.clicked.connect(self._deleteEntry)
     buttons.addWidget(button)
     dataDisplay = QTableView()
     dataDisplay.setModel(PhoneDataModel())
     layout = QVBoxLayout()
     layout.addLayout(entry)
     layout.addLayout(buttons)
     layout.addWidget(dataDisplay)
     self.setLayout(layout)
     self.show()
예제 #4
0
파일: bug_854.py 프로젝트: Hasimir/PySide
 def testSetModel(self):
     model = VirtualList()
     model._getItemCalled = False
     table = QTableView()
     table.setModel(model)
     table.show()
     self.assertFalse(model._getItemCalled)
예제 #5
0
class QuickOrderViewWidget(SubFrame):
    def __init__(self, parent):
        super(QuickOrderViewWidget, self).__init__("Quick view", None, parent)

        self._table_model = QStandardItemModel(1, 2, None)
        self.table_view = QTableView(self)
        self.table_view.setModel(self._table_model)
        self.layout().addWidget(self.table_view)

        self._table_model.setHorizontalHeaderLabels(
            ['Part Nr.', 'Description'])

        self.table_view.verticalHeader().hide()
        headers_view = self.table_view.horizontalHeader()
        headers_view.setResizeMode(0, QHeaderView.ResizeToContents)
        headers_view.setResizeMode(1, QHeaderView.Stretch)

    def selected_order(self, cur, prev):
        if cur.isValid():
            order_id = cur.model().index(cur.row(), 0).data(Qt.UserRole)

            self._table_model.removeRows(0, self._table_model.rowCount())
            row = 0
            for label, description in dao.order_dao.load_quick_view(order_id):
                self._table_model.appendRow(
                    [QStandardItem(label),
                     QStandardItem(description)])
예제 #6
0
 def testSetModel(self):
     model = VirtualList()
     model._getItemCalled = False
     table = QTableView()
     table.setModel(model)
     table.show()
     self.assertFalse(model._getItemCalled)
예제 #7
0
파일: mainwindow.py 프로젝트: Hydrael/4ca
    def _addtabondemand(self, thread):
        """Adds a new tab for the given thread, if it doesn't exist yet.
        If it does, it will be made the current tab.
        @param thread Instance of FourChanThreahHeader
        """
        i = thread.id_()
        if not i in self._openthreads.keys():
            table = QTableView(self)
            table.setModel(LiveFeedModel(self))
            table.setAlternatingRowColors(True)
            table.setEditTriggers(QAbstractItemView.NoEditTriggers)
            table.setIconSize(QSize(192, 192))
            table.horizontalHeader().setVisible(False)
            table.horizontalHeader().setDefaultSectionSize(192)
            table.horizontalHeader().setStretchLastSection(True)
            table.verticalHeader().setVisible(False)
            table.verticalHeader().setDefaultSectionSize(192)

            table.doubleClicked.connect(self._showlivepost)

            idx = self.tabPosts.addTab(table, "/%s/%s" % (thread.forum(), i))
            self._openthreads[i] = (idx, thread, table)
            fct = FourChanThread(
                    FourChanThreadUrl(thread.url()), self._masterobserver)
            fct.postadded.connect(self._updatethread)
            self._masterobserver.addobserver(
                    FourChanThreadObserver(fct, parent=self))
            fct.refresh(True)
        else:
            idx = self._openthreads[i][0]
        self.tabPosts.setCurrentIndex(idx)
예제 #8
0
파일: loader.py 프로젝트: jschloer/keyplus
    def __init__(self, parent, header, device_settings, firmware_settings, *args):
        QDialog.__init__(self, parent, *args)
        self.setGeometry(300, 200, 570, 450)
        self.setWindowTitle("Device information")
        table_model = DeviceInformationTable(self, header, device_settings)
        dev_settings_table = QTableView()
        dev_settings_table.setModel(table_model)

        table_model = DeviceInformationTable(self, header, firmware_settings)
        fw_settings_table = QTableView()
        fw_settings_table.setModel(table_model)

        # set font
        # font = QFont("monospace", 10)
        font = QFont("", 10)
        dev_settings_table.setFont(font)
        fw_settings_table.setFont(font)
        # set column width to fit contents (set font first!)
        dev_settings_table.resizeColumnsToContents()
        fw_settings_table.resizeColumnsToContents()

        tab_view = QTabWidget()
        tab_view.addTab(dev_settings_table, "User settings")
        tab_view.addTab(fw_settings_table, "Firmware settings")

        layout = QVBoxLayout(self)
        layout.addWidget(tab_view)
        self.setLayout(layout)
예제 #9
0
    def __init__(self, parent):
        super(FilteredTable, self).__init__(parent)

        self.model = QStandardItemModel(600, 600)
        for i in range(self.model.rowCount()):
            for j in range(self.model.columnCount()):
                self.model.setData(self.model.index(i, j), str(i * j),
                                   Qt.DisplayRole)

        self.m = FilteringModel(self)
        self.m.setSourceModel(self.model)

        d = ['a'] * 300 + ['b'] * 200 + ['c'] * 99 + ['d']
        self.m.setIndexData(d)

        t = QTableView(self)
        t.setModel(self.m)

        self.line_in = QLineEdit(self)
        self.line_in.textChanged.connect(self.m.setFilterFixedString)

        l = QVBoxLayout()
        l.addWidget(self.line_in)
        l.addWidget(t)
        self.setLayout(l)
예제 #10
0
    def setupTabs(self):
        """ Setup the various tabs in the AddressWidget. """
        groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"]

        for group in groups:
            proxyModel = QSortFilterProxyModel(self)
            proxyModel.setSourceModel(self.tableModel)
            proxyModel.setDynamicSortFilter(True)

            tableView = QTableView()
            tableView.setModel(proxyModel)
            tableView.setSortingEnabled(True)
            tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
            tableView.horizontalHeader().setStretchLastSection(True)
            tableView.verticalHeader().hide()
            tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            tableView.setSelectionMode(QAbstractItemView.SingleSelection)

            # This here be the magic: we use the group name (e.g. "ABC") to
            # build the regex for the QSortFilterProxyModel for the group's
            # tab. The regex will end up looking like "^[ABC].*", only 
            # allowing this tab to display items where the name starts with 
            # "A", "B", or "C". Notice that we set it to be case-insensitive.
            reFilter = "^[%s].*" % group

            proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive))
            proxyModel.setFilterKeyColumn(0) # Filter on the "name" column
            proxyModel.sort(0, Qt.AscendingOrder)

            tableView.selectionModel().selectionChanged.connect(self.selectionChanged)

            self.addTab(tableView, group)
예제 #11
0
    def testReferenceCountingWhenDeletingReferrer(self):
        '''Tests reference count of model object referred by deceased view object.'''
        model = TestModel()
        refcount1 = getrefcount(model)
        view = QTableView()
        view.setModel(model)
        self.assertEqual(getrefcount(view.model()), refcount1 + 1)

        del view
        self.assertEqual(getrefcount(model), refcount1)
예제 #12
0
    def testReferenceCountingWhenDeletingReferrer(self):
        '''Tests reference count of model object referred by deceased view object.'''
        model = TestModel()
        refcount1 = getrefcount(model)
        view = QTableView()
        view.setModel(model)
        self.assertEqual(getrefcount(view.model()), refcount1 + 1)

        del view
        self.assertEqual(getrefcount(model), refcount1)
예제 #13
0
파일: hubbub.py 프로젝트: hoozifachi/hubbub
class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        
        
        self.layout = QVBoxLayout(self)
        
        self.grid = QTableView()
        self.grid.setModel(TaskTableModel(TaskView()))
        
        self.layout.addWidget(self.grid)
예제 #14
0
파일: gui05.py 프로젝트: yysynergy/pparser
class skillsWindow(QDialog):
    def __init__(self, dataModel, oberTablo):
        QDialog.__init__(self)
        self.setWindowTitle('All Skills')
        self.setWindowIcon(QIcon('elance.ico'))
        self.oberTablo = oberTablo
        #create & configure tablewiew
        self.table_view = QTableView()
        self.table_view.setModel(dataModel)
        self.table_view.setSortingEnabled(True)
        self.table_view.sortByColumn(1, Qt.DescendingOrder)
        self.table_view.resizeColumnsToContents()
        self.table_view.resizeRowsToContents()
        #http://stackoverflow.com/questions/7189305/set-optimal-size-of-a-dialog-window-containing-a-tablewidget
        #http://stackoverflow.com/questions/8766633/how-to-determine-the-correct-size-of-a-qtablewidget
        w = 0
        w += self.table_view.contentsMargins().left() +\
             self.table_view.contentsMargins().right() +\
             self.table_view.verticalHeader().width()
        w += qApp.style().pixelMetric(QStyle.PM_ScrollBarExtent)
        for i in range(len(self.table_view.model().header)):
            w += self.table_view.columnWidth(i)
        self.table_view.horizontalHeader().setStretchLastSection(True)
        self.table_view.setMinimumWidth(w)
        
        # create two buttons
        self.findEntries = QPushButton('Find entries')
        self.findEntries.clicked.connect(self.ApplyFilterToMainList)
        self.cancel = QPushButton('Cancel')
        self.cancel.clicked.connect(self.winClose)
        
        self.mainLayout = QGridLayout()
        self.mainLayout.addWidget(self.table_view, 0,0,1,3)
        self.mainLayout.addWidget(self.findEntries, 1,0)
        self.mainLayout.addWidget(self.cancel, 1,2)
        self.setLayout(self.mainLayout)
        self.show()
    
    def ApplyFilterToMainList(self):
        selection = self.table_view.selectionModel().selection()
        skills = []
        for selRange in selection:
            for index in selRange.indexes():
                skill = index.model().data(index, Qt.DisplayRole)
                skills.append(skill)
        self.oberTablo.model().emit(SIGNAL("modelAboutToBeReset()"))
        self.oberTablo.model().criteria = {'Skills':skills}
        self.oberTablo.model().emit(SIGNAL("modelReset()"))
        self.close()
    
    def winClose(self):
        self.close()
예제 #15
0
 def __init__(self, parent=None):
     super(MainWindow, self).__init__(parent)
     database = QSqlDatabase.addDatabase('QSQLITE')
     database.setDatabaseName('astatsscraper.db') # Better lookup logic needed
     if not database.open():
         print('Error opening database!')
     model = QSqlTableModel(db=database)
     model.setTable('steam_apps')
     table = QTableView()
     table.setEditTriggers(QAbstractItemView.NoEditTriggers)
     table.setModel(model)
     self.setCentralWidget(table)
     table.show()
예제 #16
0
 def __init__(self, parent=None):
     super(MainWindow, self).__init__(parent)
     database = QSqlDatabase.addDatabase('QSQLITE')
     database.setDatabaseName(
         'astatsscraper.db')  # Better lookup logic needed
     if not database.open():
         print('Error opening database!')
     model = QSqlTableModel(db=database)
     model.setTable('steam_apps')
     table = QTableView()
     table.setEditTriggers(QAbstractItemView.NoEditTriggers)
     table.setModel(model)
     self.setCentralWidget(table)
     table.show()
예제 #17
0
def test_database_view(qtbot, session):
    session.add(Person(name="Roger Milla"))
    session.add(Person(name="François Biyik"))
    session.add(Person(name="Salvatore Schillaci"))
    session.commit()

    persons = DatabaseObjectModel(Person, session)
    persons.addAttributeColumn("name", "Name")
    assert persons.data(ModelIndexDuck(0, 0), Qt.DisplayRole) == "Roger Milla"

    view = QTableView()
    view.setModel(persons)
    persons.appendObject(Person(name="Claudio Cannigia"))
    persons.removeObject(0)
    qtbot.addWidget(view)
    view.show()
예제 #18
0
class Blew(QWidget):
    def __init__(self):
        super(Blew, self).__init__()
        self.setWindowModality(Qt.NonModal)
        self.setWindowFlags(
            Qt.FramelessWindowHint)  # Qt.Tool | Qt.FramelessWindowHint

        l = QHBoxLayout()
        self.items_view = QTableView()

        # Make the dropdown nice
        l.setContentsMargins(0, 0, 0, 0)
        self.items_view.horizontalHeader().setStretchLastSection(True)
        self.items_view.horizontalHeader().hide()
        self.items_view.verticalHeader().hide()
        self.items_view.setShowGrid(False)
        self.setMinimumSize(300, 100)

        self.model = QuickComboModel(self)
        self.items_view.setModel(self.model)
        l.addWidget(self.items_view)
        self.setLayout(l)

    def get_current_completion(self):
        """ Get the currently selected completion """
        return self.items_view.currentIndex().data()

    @Slot(list)
    def set_possible_completions(self, completions):
        if completions:
            self.model.buildModelFromArray(completions)
            # self.show()
        else:
            self.model.clear()
            self.hide()

    completion_discarded = Signal()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            event.ignore()
            self.hide()
            self.completion_discarded.emit()

        return super(Blew, self).keyPressEvent(event)
예제 #19
0
    def __init__(self, table_model, _completerSetupFunction=None, *args):
        QWidget.__init__(self, *args)
        # setGeometry(x_pos, y_pos, width, height)
        self.setGeometry(300, 200, 570, 450)
        self.setWindowTitle("QTableView + completer example")
        table_view = QTableView()
        table_view.setModel(table_model)
        # set column width to fit contents (set font first!)
        table_view.resizeColumnsToContents()
        table_view.resizeRowsToContents()
        
        if _completerSetupFunction is not None:
            delegate = CompleterDelegate(table_view, _completerSetupFunction)
            table_view.setItemDelegateForColumn(1, delegate)            

        layout = QVBoxLayout(self)
        layout.addWidget(table_view)
        self.setLayout(layout)
예제 #20
0
    def setup_ui(self):
        splitter = QSplitter(self)
        left = QWidget(splitter)
        left.setLayout(QVBoxLayout(left))
        left.layout().addWidget(QLabel('QTableView', left))
        tableview = QTableView(left)
        tableview.setModel(TableModel(tableview))
        left.layout().addWidget(tableview)
        splitter.addWidget(left)
        right = QWidget(splitter)
        right.setLayout(QVBoxLayout(right))
        right.layout().addWidget(QLabel('QTableWidget', right))
        # create a table widget for DATA
        tablewidget = QTableWidget(len(DATA), len(DATA[1]), right)
        right.layout().addWidget(tablewidget)
        splitter.addWidget(right)
        self.setCentralWidget(splitter)

        # add tablewidget data
        self.add_data(tablewidget)
    def setup_ui(self):
        splitter = QSplitter(self)
        left = QWidget(splitter)
        left.setLayout(QVBoxLayout(left))
        left.layout().addWidget(QLabel('QTableView', left))
        tableview = QTableView(left)
        tableview.setModel(TableModel(tableview))
        left.layout().addWidget(tableview)
        splitter.addWidget(left)
        right = QWidget(splitter)
        right.setLayout(QVBoxLayout(right))
        right.layout().addWidget(QLabel('QTableWidget', right))
        # create a table widget for DATA
        tablewidget = QTableWidget(len(DATA), len(DATA[1]), right)
        right.layout().addWidget(tablewidget)
        splitter.addWidget(right)
        self.setCentralWidget(splitter)

        # add tablewidget data
        self.add_data(tablewidget)
예제 #22
0
    def testReferenceCounting(self):
        '''Tests reference count of model object referred by view objects.'''
        model1 = TestModel()
        refcount1 = getrefcount(model1)
        view1 = QTableView()
        view1.setModel(model1)
        self.assertEqual(getrefcount(view1.model()), refcount1 + 1)

        view2 = QTableView()
        view2.setModel(model1)
        self.assertEqual(getrefcount(view2.model()), refcount1 + 2)

        model2 = TestModel()
        view2.setModel(model2)
        self.assertEqual(getrefcount(view1.model()), refcount1 + 1)
예제 #23
0
    def testReferenceCounting(self):
        '''Tests reference count of model object referred by view objects.'''
        model1 = TestModel()
        refcount1 = getrefcount(model1)
        view1 = QTableView()
        view1.setModel(model1)
        self.assertEqual(getrefcount(view1.model()), refcount1 + 1)

        view2 = QTableView()
        view2.setModel(model1)
        self.assertEqual(getrefcount(view2.model()), refcount1 + 2)

        model2 = TestModel()
        view2.setModel(model2)
        self.assertEqual(getrefcount(view1.model()), refcount1 + 1)
예제 #24
0
class BrowserWindow(QMainWindow):

    MO_ROLE = Qt.UserRole+1

    def __init__(self, conn):
        super(BrowserWindow, self).__init__()
        self._conn = conn
        self._resolver = AsyncResolver()
        self._resolver.object_resolved.connect(self._data_resolved)
        self._resolver.start()
        self._init_models()
        self._init_gui()
        self._init_data()
        self._init_connections()

    def __del__(self):
        self._resolver.stop_work()
        self._resolver.terminate()

    def _init_models(self):
        self._hierarchy_model = QStandardItemModel()
        self._hierarchy_model.setColumnCount(2)
        self._hierarchy_model.setHorizontalHeaderLabels(['class', 'dn'])
        self._details_model = QStandardItemModel()
        self._details_model.setColumnCount(2)
        self._details_model.setHorizontalHeaderLabels(['Property', 'Value'])

    def _init_gui(self):
        self._widget = QSplitter(self, Qt.Horizontal)
        self._hierarchy_view = QTreeView(self._widget)
        self._details_view = QTableView(self._widget)

        self._widget.addWidget(self._hierarchy_view)
        self._widget.addWidget(self._details_view)
        self._widget.setStretchFactor(0, 2)
        self._widget.setStretchFactor(1, 1)
        self.setCentralWidget(self._widget)

        self._hierarchy_view.setModel(self._hierarchy_model)
        self._details_view.setModel(self._details_model)

        self._hierarchy_view.expanded.connect(self._mo_item_expand)

    def _init_data(self):
        item = self._row_for_mo(self._conn.resolve_dn(''))
        self._hierarchy_model.insertRow(0, item)

    def _init_connections(self):
        self.connect(self._resolver,
                        SIGNAL('object_resolved(QVariant)'),
                     self,
                        SLOT('_data_resolved(QVariant)'))
        self._hierarchy_view.activated.connect(self._item_activated)
        #self.connect(self._hierarchy_view.selectionModel(),
        #                SIGNAL('currentChanged(QModelIndex,QModelIndex)'),
        #             self,
        #                SLOT('_current_changed(QModelIndex, QModelIndex)'))
        self.connect(self._hierarchy_view.selectionModel(),
                        SIGNAL('activated(QModelIndex)'),
                     self,
                        SLOT('_item_activated(QModelIndex)'))


    def _row_for_mo(self, mo):
        row = [QStandardItem(mo.ucs_class), QStandardItem(mo.dn)]
        for item in row:
            item.setEditable(False)
        row[0].appendColumn([QStandardItem('Loading...')])
        row[0].setData(mo, self.MO_ROLE)
        return row

    def _add_mo_in_tree(self, mo, index=QtCore.QModelIndex()):
        item = None
        if index.isValid():
            item = self._hierarchy_model.itemFromIndex(index)
        else:
            item = self._get_item_for_dn(self._parent_dn(mo.dn))
        if item:
            item.appendColumn([self._row_for_mo(mo)[0]])
        self.auto_width()

    def _add_mos_in_tree(self, mos, index=QtCore.QModelIndex()):
        item = None
        if index.isValid():
            item = self._hierarchy_model.itemFromIndex(index)
        else:
            if not mos:
                return
            item = self._get_item_for_dn(self._parent_dn(mos[0].dn))
        while item.columnCount():
            item.removeColumn(0)
        items = map(self._row_for_mo, mos)
        if items:
            for x in xrange(len(items[0])):
                item.appendColumn([row[x] for row in items])
        self.auto_width()

    @staticmethod
    def _parent_dn(dn):
        parent_dn, _, rn = dn.rpartition('/')
        return parent_dn

    def _get_item_for_dn(self, dn):
        parent_dn = dn
        items = self._hierarchy_model.findItems(parent_dn, column=1)
        if items:
            return self._hierarchy_model.item(items[0].row())
        return None

    @QtCore.Slot('_data_resolved(QVariant)')
    def _data_resolved(self, datav):
        print 'Data resolved: ', datav
        index, data = datav
        if isinstance(data, UcsmObject):
            self._add_mo_in_tree(data, index=index)
        else:
            self._add_mos_in_tree(data, index=index)

    @QtCore.Slot('_current_changed(QModelIndex,QModelIndex)')
    def _current_changed(self, curr, prev):
        self._item_activated(curr)

    @QtCore.Slot('_item_activated(QModelIndex)')
    def _item_activated(self, index):
        print 'Activated: %s data %s' % (index, index.data(self.MO_ROLE))
        if index.sibling(0, 0).isValid():
            index = index.sibling(0, 0)
            data = index.data(self.MO_ROLE)
            self.set_detail_object(data)

    def _mo_item_expand(self, index):
        obj = index.data(self.MO_ROLE)
        print 'Expanded object: %s' % obj
        try:
            self._resolver.add_task(lambda: (index,
                                        self._conn.resolve_children(obj.dn)))
        except (KeyError, AttributeError):
            QtGui.QMessageBox.critical(0, 'Error', 'Object does not have dn')

    def auto_width(self):
        for view in [self._hierarchy_view, self._details_view]:
            for col in xrange(view.model().columnCount()):
                view.resizeColumnToContents(col)

    def set_detail_object(self, object):
        self._details_model.removeRows(0, self._details_model.rowCount())
        for k, v in object.attributes.iteritems():
            row = [QStandardItem(k), QStandardItem(v)]
            for item in row:
                item.setEditable(False)
            self._details_model.appendRow(row)
        self.auto_width()
예제 #25
0
class uiManager(QMainWindow):
	def __init__(self):
		super(uiManager, self).__init__()

		self.setMinimumSize(900,500)
		self.setWindowTitle("Manage")

		self.aFileModel = FileModel() # Add files
		self.sFileModel = FileModel() # Queried files
		self.eFileModel = FileModel() # Editing files

		self.tabWidget = QTabWidget()
		self.setCentralWidget(self.tabWidget)

		self.defActions()

		self.addTab()
		self.searchTab()
		self.editTab()
		self.testtab()

		self.statusBar().showMessage("Hi.")


	def defActions(self):
		self.findAct = QAction("+", self, triggered=self.findFilesDlg)
		self.dropAddTabAct = QAction("-", self, shortcut="Delete",
			triggered=self.dropAddTabRows)
		self.dropEditTabAct = QAction("-", self, shortcut="Delete",
			triggered=self.dropEditTabRows)


	def dropEditTabRows(self):
		self.dropFiles(self.eFileTable, self.eFileModel)


	def dropAddTabRows(self):
		self.dropFiles(self.aFileTable, self.aFileModel)


	def testtab(self):
		self.test = QWidget()
		self.tabWidget.addTab(self.test, "WORDS")
		self.tabWidget.setCornerWidget(self.test)


	def addTab(self):

		self.aFileTable = QTableView()
		self.aFileTable.setModel(self.aFileModel)
		self.aFileTable.setSelectionBehavior(QAbstractItemView.SelectRows)

		self.setColumnsWidths(self.aFileTable)

		self.addWidget = QWidget()

		vLayout = QVBoxLayout()
		vLayout.addWidget(self.aFileTable)

		addBtn = QToolButton()
		addBtn.setDefaultAction(self.findAct)
		# addBtn.clicked.connect(self.findFilesDlg)

		dropBtn = QToolButton()
		dropBtn.setDefaultAction(self.dropAddTabAct)
		# rmvBtn.clicked.connect(self.rmvFiles)

		insBtn = QPushButton("Track")
		insBtn.clicked.connect(self.insert)

		hLayout = QHBoxLayout()

		hLayout.addWidget(addBtn)
		hLayout.addWidget(dropBtn)
		hLayout.addStretch(1)		
		hLayout.addWidget(insBtn)

		vLayout.addLayout(hLayout)

		self.addWidget.setLayout(vLayout)

		self.tabWidget.addTab(self.addWidget, u"Add")


	def searchTab(self):

		# sFileModel + view tab
		self.sFileTable = QTableView()
		self.sFileTable.setModel(self.sFileModel)
		self.sFileTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
		self.sFileTable.setSelectionBehavior(QAbstractItemView.SelectRows)

		self.setColumnsWidths(self.sFileTable)

		self.searchWidget = QWidget()

		# Horizontal layout
		# Button, Line Edit, Button
		hLayout = QHBoxLayout()
		self.searchBox = QLineEdit()
		self.searchBox.returnPressed.connect(self.searchdb)
		hLayout.addWidget(self.searchBox)

		searchBtn = QPushButton("Search")
		searchBtn.clicked.connect(self.searchdb)
		hLayout.addWidget(searchBtn)

		# Vertical Layout
		vLayout = QVBoxLayout()
		vLayout.addLayout(hLayout)
		vLayout.addWidget(self.sFileTable)

		# sub horiz box
		subHLayout = QHBoxLayout()
		subHLayout.addStretch(1)
		
		editBtn = QPushButton("Edit -->")
		editBtn.clicked.connect(self.addToEditTab)

		subHLayout.addWidget(editBtn)
		vLayout.addLayout(subHLayout)

		self.searchWidget.setLayout(vLayout)
		self.tabWidget.addTab(self.searchWidget, u"Retrieve")


	def editTab(self):
		
		self.eFileTable = QTableView()
		self.eFileTable.setModel(self.eFileModel)
		self.eFileTable.setSelectionBehavior(QAbstractItemView.SelectRows)

		self.setColumnsWidths(self.eFileTable)

		self.editWidget = QWidget()

		vLayout = QVBoxLayout()
		vLayout.addWidget(self.eFileTable)

		dropBtn = QToolButton()
		dropBtn.setDefaultAction(self.dropEditTabAct)

		undBtn = QPushButton("Undo Delete")
		undBtn.clicked.connect(self.undeleteFiles)

		rmvBtn = QPushButton("Delete")
		rmvBtn.clicked.connect(self.deleteFiles)

		cmtBtn = QPushButton("Update")
		cmtBtn.clicked.connect(self.update)

		hLayout = QHBoxLayout()
		hLayout.addWidget(dropBtn)
		hLayout.addStretch(1)
		hLayout.addWidget(undBtn)
		hLayout.addWidget(rmvBtn)
		hLayout.addWidget(cmtBtn)

		vLayout.addLayout(hLayout)

		self.editWidget.setLayout(vLayout)

		self.tabWidget.addTab(self.editWidget, u"Edit")


	def setColumnsWidths(self, table):
		table.setColumnWidth(0, 438)
		table.horizontalHeader().setStretchLastSection(True)


	def undeleteFiles(self):
		delfiles = self.eFileModel.delfiles
		for file in delfiles:
			path, tags = file.path, file.tags
			self.addToModel(self.eFileModel, path, tags, True)
		self.eFileModel.delfiles = []


	# Adds files to the models delete list
	# for removal from the DB on next update()
	def deleteFiles(self):
		indexes = self.getSRIndexes(self.eFileTable)

		for index in indexes:
			self.eFileModel.delList(index.row())
			self.eFileModel.removeRows(index.row())
		self.statusBar().showMessage("Pending Changes")


	# Drop files from a table and model
	def dropFiles(self, table, model):
		indexes = self.getSRIndexes(table)

		for index in indexes:
			model.removeRows(index.row())


	# Inserts files into the DB from the add model
	def insert(self):
		p = self.aFileModel.insert()
		if p:
			msgDuplBox = QMessageBox()
			msgDuplBox.setText('\n'.join(p) + 
				"\n\n...file(s) already being tracked.")
			msgDuplBox.exec_()


	def update(self):
		self.eFileModel.update()

	
	''' Order of user selection matters in the view. As a user
	selects an item it is entered into the list of selected rows.
	To remove the correct items first you have to sort the list,
	then reverse it to remove items from the bottom up to prevent
	a row number pointing at the wrong entry because an entry
	above it was already removed.'''
	def getSRIndexes(self, table):
		indexes = table.selectionModel().selectedRows()
		indexes.sort()
		indexes.reverse()
		return indexes


	def findFilesDlg(self):
		finder = getFilesDlg(self)
		finder.sendPaths.connect(self.addToAddTab)
		finder.show()


	@Slot(list)
	def addToAddTab(self, list):
		for path in list:

			if self.colCheck(self.aFileModel, path):

				self.addToModel(self.aFileModel, path)


	def addToSearchTab(self, qresults):
		if qresults:

			self.sFileModel.reset()

			for file in qresults:

				path,tags = file
				self.addToModel(self.sFileModel, path, tags)


	def addToEditTab(self):
		# Need to make sure what they are adding isn't already
		# present in the edit model's files or delfiles lists
		indexes = self.getSRIndexes(self.sFileTable)

		# save original path as update reference for db
		oldpath = True

		for index in indexes:

			path, tags = self.sFileModel.dataTuple(index)

			if self.colCheck(self.eFileModel, path):
			
				self.addToModel(self.eFileModel, path, tags, oldpath)

				self.sFileModel.removeRows(index.row())


	def addToModel(self, model, path, tags=None, oldpath=False):

			model.insertRows(0)

			ix = model.index(0, 0, QModelIndex())
			model.setData(ix, path, Qt.EditRole, oldpath)

			ix = model.index(0, 1, QModelIndex())
			model.setData(ix, tags, Qt.EditRole, oldpath)


	def colCheck(self, model, path):
		# THIS IS REALLY SLOW
		# Linear search, 
		if model.files:
			for file in model.files:
				if path == file.path:
					return False
		return True


	def searchdb(self):
		thedb = myDB()
		query = thedb.query(self.searchBox.text())
		self.addToSearchTab(query)
예제 #26
0
class ConsoleWidget(QMainWindow):
    def __init__(self):
        super(ConsoleWidget, self).__init__()
        self.setWindowTitle('1c query')

        self._connection = None

        self._home = os.path.expanduser('~/%s' % QApplication.applicationName())
        if not os.path.isdir(self._home):
            os.mkdir(self._home)

        self.queryToolBar = self.addToolBar('Query')
        self.queryAction = self.queryToolBar.addAction('Run', self.executeQuery)
        self.queryAction.setDisabled(True)

        uri_history = list()
        path = os.path.join(self._home, 'uri_history.txt')
        if os.path.isfile(path):
            uri_history = open(path, 'r').read().split('\n')

        self.connectionToolBar = self.addToolBar('Connection')
        self.connectionUriCombo = QComboBox(self)
        self.connectionUriCombo.setEditable(True)
        if not uri_history:
            self.connectionUriCombo.addItem('File="";usr="";pwd="";')
            self.connectionUriCombo.addItem('Srvr="{host}";Ref="{ref}";Usr="******";Pwd="{password}";')
        else:
            self.connectionUriCombo.addItems(uri_history)
            self.connectionUriCombo.setCurrentIndex(len(uri_history) - 1)
        self.connectionUriCombo.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Maximum)
        self.connectionToolBar.addWidget(self.connectionUriCombo)

        self.onesVersionCombo = QComboBox(self)
        self.onesVersionCombo.addItems(['8.3', '8.2', '8.1', '8.0'])
        self.onesVersionCombo.setCurrentIndex(0)
        self.connectionToolBar.addWidget(self.onesVersionCombo)
        self.connectAction = self.connectionToolBar.addAction('Connect', self.connectOneS)
        self.disconnectAction = self.connectionToolBar.addAction('Disconnect', self.disconnectOneS)
        self.disconnectAction.setDisabled(True)

        self.logEdit = QPlainTextEdit(self)
        self.logDock = QDockWidget('Log', self)
        self.logDock.setWidget(self.logEdit)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.logDock, Qt.Horizontal)

        self.splitter = QSplitter(Qt.Vertical, self)
        self.setCentralWidget(self.splitter)

        self.sqlEdit = QTextEdit(self)
        self.sqlEdit.setLineWrapMode(QTextEdit.NoWrap)

        path = os.path.join(self._home, 'last-sql.txt')
        if os.path.isfile(path):
            sql = open(path, 'r').read()
            self.sqlEdit.setText(sql)

        self.model = QStandardItemModel(self)
        self.tableView = QTableView(self)
        self.tableView.setModel(self.model)

        self.splitter.addWidget(self.sqlEdit)
        self.splitter.addWidget(self.tableView)
        self.splitter.setStretchFactor(0, 3)
        self.splitter.setStretchFactor(1, 2)

    def query(self, sql):
        if not self._connection:
            self.logEdit.appendPlainText('No connection')
            return None

        try:
            query = self._connection.NewObject('Query', sql)
            result = query.Execute()
        except Exception as e:
            self.logEdit.appendPlainText(str(e))
            return None

        return result

    def refresh(self, result):
        self.model.clear()

        columns = list()
        result_columns = result.Columns
        for index in range(result_columns.Count()):
            name = result_columns.Get(index).Name
            columns.append(name)

        self.model.setColumnCount(len(columns))
        for section, name in enumerate(columns):
            self.model.setHeaderData(section, Qt.Horizontal, name)

        select = result.Choose()
        self.logEdit.appendPlainText('Selected %d records' % select.Count())
        while select.Next():
            items = list()
            for index in range(len(columns)):
                value = select.Get(index)

                item = QStandardItem('')
                if isinstance(value, bool):
                    item.setText(value and 'Yes' or 'No')

                elif isinstance(value, (int, str)):
                    item.setText(str(value))

                elif isinstance(value, datetime.datetime):
                    item.setText(value.strftime('%Y.%m.%d %H:%M:%S'))

                else:
                    item.setText(str(value))
                items.append(item)

            self.model.appendRow(items)

    @Slot()
    def executeQuery(self):
        sql = self.sqlEdit.toPlainText()
        result = self.query(sql)
        if result:
            path = os.path.join(self._home, 'last-sql.txt')
            open(path, 'w').write(sql)
            self.refresh(result)

    @Slot()
    def connectOneS(self):
        uri = self.connectionUriCombo.currentText().strip()
        if not uri:
            self.logEdit.appendPlainText('Need a connection string')
            return

        version = self.onesVersionCombo.currentText()
        comName = "V%s.COMConnector" % str(version).replace('.', '')

        pythoncom.CoInitialize()
        try:
            obj = win32com.client.Dispatch(comName)
            self._connection = obj.Connect(uri)
        except Exception as e:
            self.logEdit.appendPlainText(str(e))
            return

        self.connectAction.setDisabled(True)
        self.disconnectAction.setEnabled(True)
        self.queryAction.setEnabled(True)

        uri_history = list()
        for i in range(self.connectionUriCombo.count()):
            uri_history.append(self.connectionUriCombo.itemText(i))

        if uri not in uri_history:
            self.connectionUriCombo.clearEditText()
            self.connectionUriCombo.addItem(uri)
            self.connectionUriCombo.setCurrentIndex(len(uri_history))
            uri_history.append(uri)
            path = os.path.join(self._home, 'uri_history.txt')
            open(path, 'w').write('\n'.join(uri_history))

    @Slot()
    def disconnectOneS(self):
        pythoncom.CoUninitialize()
        self._connection = None
        self.connectAction.setEnabled(True)
        self.disconnectAction.setDisabled(True)
        self.queryAction.setDisabled(True)
예제 #27
0
class TimeTracksOverviewWidget(QWidget):

    @Slot(QModelIndex)
    def cell_entered(self,ndx):
        chrono = datetime.now()

        employee = self.employees[ndx.row()]

        a = max(1,ndx.column())
        d = date(self.base_date.year,self.base_date.month,min(calendar.monthrange(self.base_date.year,self.base_date.month)[1], max(1,ndx.column())))
        # print employee, d

        # Fill in the timetracks report panel ----------------------------

        # First we read the timetrackss and their associated OrderPart

        t_start = datetime(d.year,d.month,d.day,0,0,0,0)
        t_end = datetime(d.year,d.month,d.day,23,59,59,999999)

        # FIXME not abstract enough
        # FIXME This should be in the DAO

        tt = session().query(TimeTrack,OrderPart).\
            join(TaskOnOperation).join(Operation).join(ProductionFile).join(OrderPart).\
            filter(and_(TimeTrack.employee == employee,
                        TimeTrack.start_time >= t_start,
                        TimeTrack.start_time <= t_end)).order_by(asc(TimeTrack.start_time)).all()

        tt += session().query(TimeTrack,Order).join(TaskOnOrder).join(Order).filter(and_(TimeTrack.employee == employee, TimeTrack.start_time >= t_start, TimeTrack.start_time <= t_end)).order_by(asc(TimeTrack.start_time)).all()

        tt += session().query(TimeTrack,OperationDefinition).join(TaskOnNonBillable).join(OperationDefinition).filter(and_(TimeTrack.employee == employee, TimeTrack.start_time >= t_start, TimeTrack.start_time <= t_end)).order_by(asc(TimeTrack.start_time)).all()


        # Fill in the report panel ---------------------------------------

        self.hours_on_day_subframe.set_title(_("Hours worked on the {} by {}").format(date_to_s(d,True),employee.fullname))
        self.controller.model._buildModelFromObjects(map(lambda o : o[0],tt)) #     dao.timetrack_dao.all_for_employee(employee))

        # self.controller.model.row_protect_func = lambda obj,row: obj is not None and obj.managed_by_code

        ndx = 0
        for row in self.controller.model.table:
            if row[1]:
                row[0] = tt[ndx][1] # First column becomes the order
            ndx += 1

        self.controller.view.resizeColumnsToContents()


        # Fill in the time report panel ---------------------------------

        self.pointage_timestamp_prototype.set_fix_date(d)
        self.controller_actions.model._buildModelFromObjects(
            dao.task_action_report_dao.get_reports_for_employee_on_date(employee,d))


    @Slot()
    def refresh_action(self):
        global dao

        self.title_box.set_title(_("Time Records Overview - {}").format(date_to_my(self.base_date,True)))


        self.employees = dao.employee_dao.all()
        day_max = calendar.monthrange(self.base_date.year,self.base_date.month)[1]
        t_start = datetime(self.base_date.year,self.base_date.month,1)
        t_end   = datetime(self.base_date.year,self.base_date.month,day_max,23,59,59,999999)


        self._table_model.setRowCount( len(self.employees))
        self._table_model.setColumnCount( 1+day_max)

        headers = QStandardItemModel(1, 1+day_max)
        headers.setHeaderData(0, Qt.Orientation.Horizontal, _("Employee"))
        for i in range(day_max):
            headers.setHeaderData(i+1, Qt.Orientation.Horizontal, "{}".format(i+1))
        self.headers_view.setModel(headers) # qt's doc : The view does *not* take ownership
        self.header_model = headers

        row = 0
        for employee in self.employees:
            # mainlog.debug(u"refresh action employee {}".format(employee))

            self._table_model.setData(self._table_model.index(row,0),employee.fullname,Qt.DisplayRole) # FIXME Use a delegate
            self._table_model.setData(self._table_model.index(row,0),employee,Qt.UserRole) # FIXME Use a delegate

            tracks = session().query(TimeTrack).filter(and_(TimeTrack.employee_id == employee.employee_id, TimeTrack.start_time >= t_start,TimeTrack.start_time <= t_end)).all()

            # One bucket per day
            buckets = [0] * day_max
            for t in tracks:
                mainlog.debug("Bucket {}".format(t))
                buckets[t.start_time.day - 1] += t.duration

            for b in range(len(buckets)):
                if buckets[b] != 0:
                    self._table_model.setData(self._table_model.index(row,b+1),duration_to_s(buckets[b]),Qt.DisplayRole)
                else:
                    self._table_model.setData(self._table_model.index(row,b+1),None,Qt.DisplayRole)

                if buckets[b] >= 0:
                    # Clear the background
                    self._table_model.setData(self._table_model.index(row,b+1),None,Qt.BackgroundRole)
                else:
                    self._table_model.setData(self._table_model.index(row,b+1),QBrush(QColor(255,128,128)),Qt.TextColorRole)

                self._table_model.setData(self._table_model.index(row,b+1),Qt.AlignRight,Qt.TextAlignmentRole)
            row += 1


        # Compute all mondays indices
        monday = 0
        if t_start.weekday() > 0:
            monday = 7 - t_start.weekday()
        all_mondays = []

        while monday < day_max:
            all_mondays.append(monday)
            monday += 7

        today = date.today()

        for row in range(len(self.employees)):
            # Mark mondays
            for col in all_mondays:
                # col + 1 to account for the employee column
                self._table_model.setData(self._table_model.index(row,col + 1),QBrush(QColor(230,230,255)),Qt.BackgroundRole)

            # Mark today
            if today.month == self.base_date.month and today.year == self.base_date.year:
                self._table_model.setData(self._table_model.index(row,today.day),QBrush(QColor(255,255,128)),Qt.BackgroundRole)

        #for i in range(len(all_mondays)):
        self.table_view.resizeColumnsToContents()

        # mainlog.debug("Reset selection")
        ndx = self.table_view.currentIndex()

        self.table_view.selectionModel().clear()
        # self.table_view.selectionModel().clearSelection()
        # self.table_view.selectionModel().select( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select)
        # self.table_view.selectionModel().select( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select)
        self.table_view.selectionModel().setCurrentIndex( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select)

        # self.cell_entered(self.table_view.currentIndex())


    @Slot()
    def month_today(self):
        self.base_date = date.today()
        self.refresh_action()


    @Slot()
    def month_before(self):
        m = self.base_date.month

        if m > 1:
            self.base_date = date(self.base_date.year,m - 1,self.base_date.day)
        else:
            self.base_date = date(self.base_date.year - 1,12,self.base_date.day)
        self.refresh_action()

    @Slot()
    def month_after(self):
        m = self.base_date.month

        if self.base_date.year < date.today().year or m < date.today().month:
            if m < 12:
                self.base_date = date(self.base_date.year,m + 1,self.base_date.day)
            else:
                self.base_date = date(self.base_date.year + 1,1,self.base_date.day)
            self.refresh_action()

    @Slot()
    def edit_timetrack_no_ndx(self):
        ndx = self.table_view.currentIndex()
        if ndx.isValid() and ndx.column() >= 0 and ndx.row() >= 0:
            self.edit_timetrack(ndx)
        else:
            showWarningBox(_("Can't edit"),_("You must first select a day/person."))


    @Slot(QModelIndex)
    def edit_timetrack(self,ndx):
        global dao
        global user_session

        if not user_session.has_any_roles(['TimeTrackModify']):
            return

        m = self.base_date.month
        edit_date = date(self.base_date.year,m,ndx.column()) # +1 already in because of employee's names
        employee = self._table_model.data(self._table_model.index(ndx.row(),0),Qt.UserRole) # FIXME Use a delegate
        d = EditTimeTracksDialog(self,dao,edit_date)
        d.set_employee_and_date(employee,edit_date)
        d.exec_()
        if d.result() == QDialog.Accepted:
            self.refresh_action()
        d.deleteLater()


    @Slot()
    def editTaskActionReports(self):
        if not user_session.has_any_roles(['TimeTrackModify']):
            return

        m = self.base_date.month
        ndx = self.table_view.currentIndex()

        if ndx.isValid() and ndx.column() >= 0 and ndx.row() >= 0:
            edit_date = date(self.base_date.year,m,ndx.column()) # +1 already in because of employee's names
            employee = self._table_model.data(self._table_model.index(ndx.row(),0),Qt.UserRole) # FIXME Use a delegate

            d = EditTaskActionReportsDialog(dao,self,edit_date)
            d.set_employee_date(employee, edit_date)
            d.exec_()
            if d.result() == QDialog.Accepted:
                self.refresh_action()
            d.deleteLater()
        else:
            showWarningBox(_("Can't edit"),_("You must first select a day/person."))


    @Slot(QModelIndex)
    def timetrack_changed(self,ndx):

        selected_timetrack = self.controller.model.object_at(ndx)

        # Update the colors in the timetrack views
        # to show what action reports correspond to the
        # selected timetrack

        self.controller_actions.model.current_timetrack = selected_timetrack
        self.controller_actions.model.beginResetModel()
        self.controller_actions.model.endResetModel()

        # Make sure the first of the action reports is shown in the
        # table

        action_reports = self.controller_actions.model.objects
        for i in range(len(action_reports)-1,-1,-1):
            if action_reports[i] and action_reports[i].timetrack == selected_timetrack:
                self.controller_actions.view.scrollTo(self.controller_actions.model.index(i,0))
                break


    def __init__(self,parent):
        super(TimeTracksOverviewWidget,self).__init__(parent)

        self.base_date = date.today()

        headers = QStandardItemModel(1, 31 + 1)
        headers.setHeaderData(0, Qt.Orientation.Horizontal, _("Employee"))
        for i in range(31):
            headers.setHeaderData(i+1, Qt.Orientation.Horizontal, "{}".format(i+1))

        self._table_model = QStandardItemModel(1, 31+1, None)


        self.headers_view = QHeaderView(Qt.Orientation.Horizontal,self)
        self.header_model = headers
        self.headers_view.setResizeMode(QHeaderView.ResizeToContents)
        self.headers_view.setModel(self.header_model) # qt's doc : The view does *not* take ownership

        self.table_view = QTableView(None)
        self.table_view.setModel(self._table_model)
        self.table_view.setHorizontalHeader(self.headers_view)
        self.table_view.verticalHeader().hide()
        self.table_view.setAlternatingRowColors(True)
        # self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)


        navbar = NavBar(self, [ (_("Month before"), self.month_before),
                                (_("Today"),self.month_today),
                                (_("Month after"), self.month_after)])

        self.title_box = TitleWidget(_("Time Records Overview"),self,navbar)
        self.vlayout = QVBoxLayout(self)
        self.vlayout.setObjectName("Vlayout")
        self.vlayout.addWidget(self.title_box)


        self.setLayout(self.vlayout)


        self.hours_per_pers_subframe = SubFrame(_("Hours worked per person"), self.table_view, self)

        self.vlayout.addWidget(self.hours_per_pers_subframe)


        hlayout = QHBoxLayout()

        prototype = []
        prototype.append( OrderPartOnTaskPrototype(None, _('Order Part')))
        prototype.append( TaskOnOrderPartPrototype('task', _('Task'),on_date=date.today()))
        prototype.append( DurationPrototype('duration',_('Duration')))
        prototype.append( TimestampPrototype('start_time',_('Start time'),fix_date=date.today()))
        prototype.append( DatePrototype('encoding_date',_('Recorded at'),editable=False))

        self.controller = PrototypeController(self,prototype)
        self.controller.setModel(TrackingProxyModel(self,prototype))
        self.controller.view.setColumnWidth(1,300)
        self.controller.view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
        self.controller.view.horizontalHeader().setResizeMode(1,QHeaderView.Stretch)

        navbar = NavBar(self, [ (_("Edit"), self.edit_timetrack_no_ndx)])
        self.hours_on_day_subframe = SubFrame(_("Total times on day"), self.controller.view, self,navbar)
        hlayout.addWidget(self.hours_on_day_subframe)


        prototype = []
        # prototype.append( EmployeePrototype('reporter', _('Description'), dao.employee_dao.all()))

        prototype.append( TaskDisplayPrototype('task', _('Task')))
        self.pointage_timestamp_prototype = TimestampPrototype('time',_('Hour'),editable=False,fix_date=date.today())
        prototype.append( self.pointage_timestamp_prototype)
        prototype.append( TaskActionTypePrototype('kind',_('Action')))
        prototype.append( TextLinePrototype('origin_location',_('Origin')))
        prototype.append( TextLinePrototype('editor',_('Editor'),editable=False,default='master'))


        self.controller_actions = PrototypeController(self,prototype)
        self.controller_actions.setModel(ActionReportModel(self,prototype))

        navbar = NavBar(self, [ (_("Edit"), self.editTaskActionReports)])
        hlayout.addWidget(SubFrame(_("Time records"),self.controller_actions.view,self,navbar))
        self.controller_actions.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.controller_actions.view.doubleClicked.connect(self.editTaskActionReports)

        self.controller_actions.view.horizontalHeader().setResizeMode(0,QHeaderView.Stretch)
        self.controller_actions.view.horizontalHeader().setResizeMode(3,QHeaderView.ResizeToContents)
        self.controller_actions.view.horizontalHeader().setResizeMode(4,QHeaderView.ResizeToContents)

        self.vlayout.addLayout(hlayout)

        self.vlayout.setStretch(0,0)
        self.vlayout.setStretch(1,300)
        self.vlayout.setStretch(2,200)

        # self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        #self.table_view.entered.connect(self.cell_entered)

        self.table_view.selectionModel().currentChanged.connect(self.cell_entered)
        self.table_view.doubleClicked.connect(self.edit_timetrack)
        self.controller.view.selectionModel().currentChanged.connect(self.timetrack_changed)
        self.controller.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.refresh_action()
예제 #28
0
class ModelTableWidget(QWidget):

    dataChanged = Signal(QModelIndex, QModelIndex)

    class _ModelTableModel(QAbstractTableModel):
        def __init__(self):
            QAbstractTableModel.__init__(self)
            self._models = []

        def rowCount(self, *args, **kwargs):
            return len(self._models)

        def columnCount(self, *args, **kwargs):
            return 2

        def data(self, index, role=Qt.DisplayRole):
            if not index.isValid() or not (0 <= index.row() < len(self._models)):
                return None

            if role == Qt.TextAlignmentRole:
                return Qt.AlignCenter

            model = self._models[index.row()]
            if model is None:
                return ""

            if role == Qt.DisplayRole or role == Qt.ToolTipRole:
                column = index.column()
                if column == 0:
                    return str(model.type)
                elif column == 1:
                    return str(model)

            return None

        def headerData(self, section, orientation, role):
            if role != Qt.DisplayRole:
                return None
            if orientation == Qt.Horizontal:
                if section == 0:
                    return "Type"
                elif section == 1:
                    return "Model"
            elif orientation == Qt.Vertical:
                return str(section + 1)

        def flags(self, index):
            if not index.isValid():
                return Qt.ItemIsEnabled

            return Qt.ItemFlags(QAbstractTableModel.flags(self, index))

        def setData(self, index, value, role=Qt.EditRole):
            if not index.isValid() or not (0 <= index.row() < len(self._models)):
                return False

            row = index.row()
            self._models[row] = value

            self.dataChanged.emit(index, index)
            return True

        def insertRows(self, row, count=1, parent=None):
            if parent is None:
                parent = QModelIndex()
            self.beginInsertRows(parent, row, row + count - 1)

            for _ in range(count):
                self._models.insert(row, None)

            self.endInsertRows()
            return True

        def removeRows(self, row, count=1, parent=None):
            if parent is None:
                parent = QModelIndex()
            self.beginRemoveRows(parent, row, row + count - 1)

            for index in reversed(range(row, row + count)):
                self._models.pop(index)

            self.endRemoveRows()
            return True

        def append(self, model):
            self.insert(self.rowCount(), model)

        def insert(self, index, model):
            self.insertRows(index)
            self.setData(self.createIndex(index, 0), model)

        def remove(self, model):
            index = self._models.index(model)
            self.removeRows(index)

        def clear(self):
            self.removeRows(0, self.rowCount())

        def models(self):
            models = set(self._models)
            models.discard(None)
            return models

        def model(self, index):
            return self._models[index.row()]

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

        # Variables
        model = self._ModelTableModel()

        # Widgets
        self._tbl_models = QTableView()
        self._tbl_models.setModel(model)
        header = self._tbl_models.horizontalHeader()
        header.setResizeMode(QHeaderView.Stretch)
        policy = self._tbl_models.sizePolicy()
        policy.setVerticalStretch(True)
        self._tbl_models.setSizePolicy(policy)
        self._tbl_models.setSelectionMode(QTableView.SelectionMode.MultiSelection)

        # Layouts
        layout = QVBoxLayout()
        layout.addWidget(self._tbl_models)
        self.setLayout(layout)

        # Signals
        model.dataChanged.connect(self.dataChanged)

    def addModel(self, model):
        self._tbl_models.model().append(model)

    def addModels(self, models):
        for model in models:
            self.addModel(model)

    def removeModel(self, model):
        self._tbl_models.model().remove(model)

    def clear(self):
        self._tbl_models.model().clear()

    def models(self):
        return self._tbl_models.model().models()

    def currentModels(self):
        tbl_model = self._tbl_models.model()

        models = []
        for index in self._tbl_models.selectionModel().selection().indexes():
            models.append(tbl_model.model(index))

        return models
예제 #29
0
class WarningWizardPage(_OptionsWizardPage):

    class _WarningTableModel(QAbstractTableModel):

        def __init__(self, warns=None):
            QAbstractTableModel.__init__(self)
            if warns is None:
                warns = []
            self._warns = warns

        def rowCount(self, *args, **kwargs):
            return len(self._warns)

        def columnCount(self, *args, **kwargs):
            return 2

        def data(self, index, role=Qt.DisplayRole):
            if not index.isValid() or \
                    not (0 <= index.row() < len(self._warns)):
                return None

            if role == Qt.TextAlignmentRole:
                return Qt.AlignCenter

            if role != Qt.DisplayRole:
                return None

            return str(self._warns[index.row()][index.column()])

        def headerData(self, section , orientation, role):
            if role != Qt.DisplayRole:
                return None
            if orientation == Qt.Horizontal:
                if section == 0:
                    return 'Program'
                elif section == 1:
                    return 'Warning'
            elif orientation == Qt.Vertical:
                return str(section + 1)

        def flags(self, index):
            if not index.isValid():
                return Qt.ItemIsEnabled

            return Qt.ItemFlags(QAbstractTableModel.flags(self, index))

    def __init__(self, options, parent=None):
        _OptionsWizardPage.__init__(self, options, parent=parent)
        self.setTitle("Conversion warnings")

        # Widgets
        self._lbl_count = SimulationCountLabel()
        self._lbl_count.setAlignment(Qt.AlignCenter)

        # Layouts
        layout = self.layout()

        frm_line = QFrame()
        frm_line.setFrameStyle(QFrame.HLine)
        frm_line.setFrameShadow(QFrame.Sunken)
        layout.addWidget(frm_line)

        sublayout = QHBoxLayout()
        sublayout.setContentsMargins(10, 0, 10, 0)
        sublayout.addWidget(self._lbl_count)
        layout.addLayout(sublayout)

    def _initUI(self):
        # Widgets
        self._tbl_warnings = QTableView()
        self._tbl_warnings.setModel(self._WarningTableModel())
        header = self._tbl_warnings.horizontalHeader()
        header.setResizeMode(1, QHeaderView.Stretch)
        policy = self._tbl_warnings.sizePolicy()
        policy.setVerticalStretch(True)
        self._tbl_warnings.setSizePolicy(policy)

        # Layouts
        layout = _OptionsWizardPage._initUI(self)
        layout.addRow(self._tbl_warnings)

        return layout

    def initializePage(self):
        count = 0
        warns = []

        for program in self.options().programs:
            converter = program.converter_class()

            warnings.simplefilter("always")
            with warnings.catch_warnings(record=True) as ws:
                list_options = converter.convert(self.options())
                count += len(list_options)

            for w in ws:
                warns.append((program, w.message))

        model = self._WarningTableModel(warns)
        self._tbl_warnings.setModel(model)

        self._lbl_count.setValue(count)

    def validatePage(self):
        return self._lbl_count.value() > 0
예제 #30
0
class LimitWizardPage(_ExpandableOptionsWizardPage):

    class _LimitComboBoxModel(QAbstractListModel):

        def __init__(self, limits_text=None):
            QAbstractListModel.__init__(self)

            if limits_text is None:
                limits_text = {}
            self._limits_text = limits_text.copy()

            self._limits = list(limits_text.keys())

        def rowCount(self, *args, **kwargs):
            return len(self._limits)

        def data(self, index, role=Qt.DisplayRole):
            if not index.isValid() or \
                    not (0 <= index.row() < self.rowCount()):
                return None

            if role == Qt.TextAlignmentRole:
                return Qt.AlignCenter

            if role != Qt.DisplayRole:
                return None

            limit_class = self._limits[index.row()]
            return self._limits_text[limit_class]

        def add(self, limit_class):
            if limit_class not in self._limits_text:
                raise ValueError('No text defined for limit: %s' % limit_class)
            self._limits.append(limit_class)
            self.reset()

        def remove(self, limit_class):
            self._limits.remove(limit_class)
            self.reset()

        def limitClass(self, index):
            return self._limits[index]

    class _LimitTableModel(QAbstractTableModel):

        def __init__(self):
            QAbstractTableModel.__init__(self)
            self._limits = []

        def rowCount(self, *args, **kwargs):
            return len(self._limits)

        def columnCount(self, *args, **kwargs):
            return 1

        def data(self, index, role=Qt.DisplayRole):
            if not index.isValid() or \
                    not (0 <= index.row() < len(self._limits)):
                return None

            if role == Qt.TextAlignmentRole:
                return Qt.AlignCenter

            if role == Qt.DisplayRole or role == Qt.ToolTipRole:
                limit = self._limits[index.row()]
                return str(limit) if limit is not None else ''

            return None

        def headerData(self, section , orientation, role):
            if role != Qt.DisplayRole:
                return None
            if orientation == Qt.Vertical:
                return str(section + 1)

        def flags(self, index):
            if not index.isValid():
                return Qt.ItemIsEnabled

            return Qt.ItemFlags(QAbstractTableModel.flags(self, index) |
                                Qt.ItemIsEditable)

        def setData(self, index, value, role=Qt.EditRole):
            if not index.isValid() or \
                    not (0 <= index.row() < len(self._limits)):
                return False

            row = index.row()
            self._limits[row] = value

            self.dataChanged.emit(index, index)
            return True

        def insertRows(self, row, count=1, parent=None):
            if parent is None:
                parent = QModelIndex()
            self.beginInsertRows(parent, row, row + count - 1)

            for _ in range(count):
                self._limits.insert(row, None)

            self.endInsertRows()
            return True

        def removeRows(self, row, count=1, parent=None):
            if parent is None:
                parent = QModelIndex()
            self.beginRemoveRows(parent, row, row + count - 1)

            for index in reversed(range(row, row + count)):
                self._limits.pop(index)

            self.endRemoveRows()
            return True

        def append(self, limit):
            self.insert(self.rowCount(), limit)

        def insert(self, index, limit):
            self.insertRows(index)
            self.setData(self.createIndex(index, 0), limit)

        def remove(self, limit):
            index = self._limits.index(limit)
            self.removeRows(index)

        def modify(self, index, limit):
            self.setData(self.createIndex(index, 0), limit)

        def clear(self):
            self.removeRows(0, self.rowCount())

        def limits(self):
            limits = set(self._limits)
            limits.discard(None)
            return limits

        def limit(self, index):
            return self._limits[index.row()]

    class _LimitTableDelegate(QItemDelegate):

        def __init__(self, parent=None):
            QItemDelegate.__init__(self, parent)

        def createEditor(self, parent, option, index):
            return None

        def setEditorData(self, editor, index):
            pass

        def setModelData(self, editor, model, index):
            return None

    def __init__(self, options, parent=None):
        _ExpandableOptionsWizardPage.__init__(self, options, parent)
        self.setTitle('Limit')

    def _initUI(self):
        # Variables
        self._widgets = {}
        tbl_model = self._LimitTableModel()

        # Widgets
        self._cb_limit = QComboBox()
        self._cb_limit.setModel(self._LimitComboBoxModel())

        btn_limit_add = QPushButton()
        btn_limit_add.setIcon(getIcon("list-add"))

        self._tbl_limit = QTableView()
        self._tbl_limit.setModel(tbl_model)
        self._tbl_limit.setItemDelegate(self._LimitTableDelegate())
        header = self._tbl_limit.horizontalHeader()
        header.setResizeMode(QHeaderView.Stretch)
        header.hide()
        policy = self._tbl_limit.sizePolicy()
        policy.setVerticalStretch(True)
        self._tbl_limit.setSizePolicy(policy)

        tlb_limit = QToolBar()
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        tlb_limit.addWidget(spacer)
        act_remove = tlb_limit.addAction(getIcon("list-remove"), "Remove limit")
        act_clear = tlb_limit.addAction(getIcon("edit-clear"), "Clear")

        # Layouts
        layout = _ExpandableOptionsWizardPage._initUI(self)

        sublayout = QHBoxLayout()
        sublayout.addWidget(self._cb_limit, 1)
        sublayout.addWidget(btn_limit_add)
        layout.addRow("Select", sublayout)

        layout.addRow(self._tbl_limit)
        layout.addRow(tlb_limit)

        # Signals
        btn_limit_add.released.connect(self._onLimitAdd)
        act_remove.triggered.connect(self._onLimitRemove)
        act_clear.triggered.connect(self._onLimitClear)

        self._tbl_limit.doubleClicked.connect(self._onLimitDoubleClicked)

        tbl_model.dataChanged.connect(self.valueChanged)
        tbl_model.rowsInserted.connect(self.valueChanged)
        tbl_model.rowsRemoved.connect(self.valueChanged)

        return layout

    def _onLimitAdd(self):
        tbl_model = self._tbl_limit.model()
        cb_model = self._cb_limit.model()

        index = self._cb_limit.currentIndex()
        try:
            limit_class = cb_model.limitClass(index)
        except IndexError:
            return
        widget_class = self._widgets[limit_class]
        wdg_limit = widget_class()

        dialog = _LimitDialog(wdg_limit)
        if not dialog.exec_():
            return

        limit = dialog.limit()
        tbl_model.append(limit) # Insert table row
        cb_model.remove(limit.__class__) # Remove limit from combo box

    def _onLimitRemove(self):
        selection = self._tbl_limit.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Limit", "Select a row")
            return

        tbl_model = self._tbl_limit.model()
        cb_model = self._cb_limit.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            limit = tbl_model.limit(tbl_model.createIndex(row, 0))
            cb_model.add(limit.__class__) # Show limit to combo box
            tbl_model.removeRow(row) # Remove row

        if self._cb_limit.currentIndex() < 0:
            self._cb_limit.setCurrentIndex(0)

    def _onLimitClear(self):
        tbl_model = self._tbl_limit.model()
        cb_model = self._cb_limit.model()
        for row in reversed(range(tbl_model.rowCount())):
            limit = tbl_model.limit(tbl_model.createIndex(row, 0))
            cb_model.add(limit.__class__) # Show limit to combo box
            tbl_model.removeRow(row) # Remove row

        if self._cb_limit.currentIndex() < 0:
            self._cb_limit.setCurrentIndex(0)

    def _onLimitDoubleClicked(self, index):
        tbl_model = self._tbl_limit.model()
        limit = tbl_model.limit(index)
        widget_class = self._widgets[limit.__class__]
        wdg_limit = widget_class()
        wdg_limit.setValue(limit)

        dialog = _LimitDialog(wdg_limit)
        if not dialog.exec_():
            return

        tbl_model.modify(index.row(), dialog.limit())

    def initializePage(self):
        _ExpandableOptionsWizardPage.initializePage(self)

        # Clear
        self._widgets.clear()
        limits_text = {}

        # Populate combo box
        it = self._iter_widgets('pymontecarlo.ui.gui.options.limit', 'LIMITS')
        for limit_class, widget_class, programs in it:
            widget = widget_class()
            self._widgets[limit_class] = widget_class

            program_text = ', '.join(map(attrgetter('name'), programs))
            text = '{0} ({1})'.format(widget.accessibleName(), program_text)
            limits_text[limit_class] = text

            del widget

        cb_model = self._LimitComboBoxModel(limits_text)
        self._cb_limit.setModel(cb_model)
        self._cb_limit.setCurrentIndex(0)

        # Add limit(s)
        tbl_model = self._tbl_limit.model()
        tbl_model.clear()

        for limit in self.options().limits:
            tbl_model.append(limit)

    def validatePage(self):
        tbl_model = self._tbl_limit.model()

        self.options().limits.clear()
        for limit in tbl_model.limits():
            if not limit.__class__ in self._widgets:
                continue
            self.options().limits.add(limit)

        return True

    def expandCount(self):
        if self._tbl_limit.model().rowCount() == 0:
            return 0

        try:
            count = 1

            for limit in self._tbl_limit.model().limits():
                count *= len(expand(limit))

            return count
        except:
            return 0
예제 #31
0
 def testModelWithParent(self):
     view = QTableView()
     model = TestModel(None)
     view.setModel(model)
     samemodel = view.model()
     self.assertEqual(model, samemodel)
예제 #32
0
class PhotonIntensityResultWidget(_SaveableResultWidget):
    def _initUI(self):
        # Variables
        model = _PhotonIntensityResultTableModel(self.result())

        # Widgets
        self._table = QTableView()
        self._table.setModel(model)
        header = self._table.horizontalHeader()
        for i in range(1, 9):
            header.setResizeMode(i, QHeaderView.Stretch)

        # Layouts
        layout = _SaveableResultWidget._initUI(self)
        layout.addWidget(self._table)

        return layout

    def _initToolbox(self):
        toolbox = _SaveableResultWidget._initToolbox(self)

        self._itm_abbrev = _PhotonIntensityResultAbbreviationToolItem(self)
        toolbox.addItem(self._itm_abbrev, "Abbreviations")

        itm_detector = DetectorToolItem(self)
        toolbox.addItem(itm_detector, "Detector")

        self._itm_options = _PhotonIntensityResultOptionsToolItem(self)
        self._itm_options.stateChanged.connect(self._onOptionsChanged)
        toolbox.addItem(self._itm_options, "Options")

        return toolbox

    def _onOptionsChanged(self):
        model = self._table.model()
        model.setShowUncertainty(self._itm_options.showUncertainty())

        pg, cg, bg, tg = self._itm_options.showGenerated()
        pe, ce, be, te = self._itm_options.showEmitted()
        self._table.setColumnHidden(1, not pg)
        self._table.setColumnHidden(2, not pe)
        self._table.setColumnHidden(3, not cg)
        self._table.setColumnHidden(4, not ce)
        self._table.setColumnHidden(5, not bg)
        self._table.setColumnHidden(6, not be)
        self._table.setColumnHidden(7, not tg)
        self._table.setColumnHidden(8, not te)

        factor = self._itm_options.factor()
        model.setFactor(factor)

    def dump(self):
        rows = []
        rows.append(
            [
                "Transition",
                "PG",
                "PG unc",
                "PE",
                "PE unc",
                "CG",
                "CG unc",
                "CE",
                "CE unc",
                "BG",
                "BG unc",
                "BE",
                "BE unc",
                "TG",
                "TG unc",
                "TE",
                "TE unc",
            ]
        )

        result = self.result()
        for transition in result:
            row = [transition]
            row.extend(result.intensity(transition, False, False))
            row.extend(result.intensity(transition, True, False))
            row.extend(result.characteristic_fluorescence(transition, False))
            row.extend(result.characteristic_fluorescence(transition, True))
            row.extend(result.bremsstrahlung_fluorescence(transition, False))
            row.extend(result.bremsstrahlung_fluorescence(transition, True))
            row.extend(result.intensity(transition, False, True))
            row.extend(result.intensity(transition, True, True))
            rows.append(row)

        return rows
예제 #33
0
 def testModelWithParent(self):
     view = QTableView()
     model = TestModel(None)
     view.setModel(model)
     samemodel = view.model()
     self.assertEqual(model, samemodel)
예제 #34
0
class Ui_MainWindow(QMainWindow):
    """Cette classe contient tous les widgets de notre application."""
    
    defaultPalette = QPalette()
    defaultPalette.setColor(QPalette.Base, QColor("#151515"))
    defaultPalette.setColor(QPalette.Text, Qt.white)

    def __init__(self):
        super(Ui_MainWindow, self).__init__()
        # initialise la GUI avec un exemple
        self.text = "Ceci est un petit texte d'exemple."
        # les variables sont en place, initialise la GUI
        self.initUI()
        # exécute l'exemple
        self.orgText.setText(self.text)
        self.encode_text(False)
        self.logLab.setText(
            u"Saisir du texte ou importer un fichier, puis pousser \n"
            u"le bouton correspondant à l'opération souhaitée.")

    def initUI(self):
        """Met en place les éléments de l'interface."""
        # -+++++++------------------- main window -------------------+++++++- #
        self.setWindowTitle(u"Encodage / Décodage de Huffman")
        self.centerAndResize()
        centralwidget = QWidget(self)
        mainGrid = QGridLayout(centralwidget)
        mainGrid.setColumnMinimumWidth(0, 450)
        # -+++++++------------------ groupe analyse -----------------+++++++- #
        analysGroup = QGroupBox(u"Analyse", centralwidget)
        self.analysGrid = QGridLayout(analysGroup)
        #         ----------- groupe de la table des codes ----------         #
        codeTableGroup = QGroupBox(u"Table des codes", analysGroup)
        codeTableGrid = QGridLayout(codeTableGroup)
        # un tableau pour les codes
        self.codesTableModel = MyTableModel()
        self.codesTable = QTableView(codeTableGroup)
        self.codesTable.setModel(self.codesTableModel)
        self.codesTable.setFont(QFont("Mono", 8))
        self.codesTable.resizeColumnsToContents()
        self.codesTable.setSortingEnabled(True)
        codeTableGrid.addWidget(self.codesTable, 0, 0, 1, 1)
        self.analysGrid.addWidget(codeTableGroup, 1, 0, 1, 1)
        #        ----------- label du ratio de compression ----------         #
        self.ratioLab = QLabel(u"Ratio de compression: ", analysGroup)
        font = QFont()
        font.setBold(True)
        font.setWeight(75)
        font.setKerning(True)
        self.ratioLab.setFont(font)
        self.analysGrid.addWidget(self.ratioLab, 2, 0, 1, 1)
        # -+++++++-------- groupe de la table de comparaison --------+++++++- #
        self.compGroup = QGroupBox(analysGroup)
        self.compGroup.setTitle(u"Comparaisons")
        compGrid = QGridLayout(self.compGroup)
        # un tableau pour le ratio
        self.compTable = QTableWidget(self.compGroup)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.compTable.sizePolicy().hasHeightForWidth())
        self.compTable.setSizePolicy(sizePolicy)
        self.compTable.setBaseSize(QSize(0, 0))
        font = QFont()
        font.setWeight(50)
        self.compTable.setFont(font)
        self.compTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.compTable.setShowGrid(True)
        self.compTable.setGridStyle(Qt.SolidLine)
        # lignes / colonnes
        self.compTable.setColumnCount(2)
        self.compTable.setRowCount(3)
        self.compTable.setVerticalHeaderItem(0, QTableWidgetItem("Taille (bits)"))
        self.compTable.setVerticalHeaderItem(1, QTableWidgetItem("Entropie"))
        self.compTable.setVerticalHeaderItem(2, QTableWidgetItem("Taille moy. (bits)"))
        for i in range(2):
            self.compTable.verticalHeaderItem(i).setTextAlignment(
                Qt.AlignRight)
        self.compTable.setHorizontalHeaderItem(0, QTableWidgetItem("ASCII"))
        self.compTable.setHorizontalHeaderItem(1, QTableWidgetItem("Huffman"))
        
        # nom des items
        self.compTabASCIIMem = QTableWidgetItem()
        self.compTable.setItem(0, 0, self.compTabASCIIMem)
        self.compTabASCIIEnt = QTableWidgetItem()
        self.compTable.setItem(1, 0, self.compTabASCIIEnt)
        self.compTabASCIIAvg = QTableWidgetItem()
        self.compTable.setItem(2, 0, self.compTabASCIIAvg)
        self.compTabHuffMem = QTableWidgetItem()
        self.compTable.setItem(0, 1, self.compTabHuffMem)
        self.compTabHuffEnt = QTableWidgetItem()
        self.compTable.setItem(1, 1, self.compTabHuffEnt)
        self.compTabHuffAvg = QTableWidgetItem()
        self.compTable.setItem(2, 1, self.compTabHuffAvg)
        # parem du tableau
        self.compTable.horizontalHeader().setCascadingSectionResizes(False)
        self.compTable.verticalHeader().setVisible(True)
        font = QFont("Mono", 8)
        self.compTable.setFont(font)
        compGrid.addWidget(self.compTable, 1, 0, 1, 1)
        self.analysGrid.addWidget(self.compGroup, 0, 0, 1, 1)
        mainGrid.addWidget(analysGroup, 0, 1, 1, 1)
        # -+++++++----------------- groupe du texte -----------------+++++++- #
        groupBox = QGroupBox(u"Texte", centralwidget)
        textGrid = QGridLayout(groupBox)
        # -+++++++------------- groupe du texte original ------------+++++++- #
        orgTextGroup = QGroupBox(u"Texte original (Ctrl+T)", groupBox)
        orgTextGrid = QGridLayout(orgTextGroup)
        self.orgText = QTextEdit(orgTextGroup)
        self.orgText.setPalette(self.defaultPalette)
        orgTextGrid.addWidget(self.orgText, 0, 0, 1, 1)
        textGrid.addWidget(orgTextGroup, 0, 0, 1, 2)
        # -+++++++------------ groupe du texte compressé ------------+++++++- #
        compressedTextGroup = QGroupBox(u"Texte compressé (Ctrl+H)", groupBox)
        compressedTextGrid = QGridLayout(compressedTextGroup)
        self.compressedText = QTextEdit(compressedTextGroup)
        self.compressedText.setPalette(self.defaultPalette)
        compressedTextGrid.addWidget(self.compressedText, 0, 0, 1, 1)
        textGrid.addWidget(compressedTextGroup, 1, 0, 1, 2)
        # -+++++++------------ groupe pour le texte ascii -----------+++++++- #
        asciiTextGroup = QGroupBox(u"Texte ASCII", groupBox)
        asciiTextGrid = QGridLayout(asciiTextGroup)
        self.asciiText = QTextBrowser(asciiTextGroup)
        self.asciiText.setPalette(self.defaultPalette)
        asciiTextGrid.addWidget(self.asciiText, 0, 0, 1, 1)
        textGrid.addWidget(asciiTextGroup, 2, 0, 1, 2)
        # -+++++++-------------------- label de log -----------------+++++++- #
        self.logLab = QLabel(analysGroup)
        textGrid.addWidget(self.logLab, 3, 0, 1, 2)
        # -+++++++----------- bouton pour encoder le texte ----------+++++++- #
        self.encodeBut = QPushButton(groupBox)
        self.encodeBut.setStatusTip(
            u"Cliquez sur ce bouton pour encoder le texte original.")
        self.encodeBut.setText(u"ENCODER")
        self.encodeBut.clicked.connect(self.encode_text)
        textGrid.addWidget(self.encodeBut, 4, 0, 1, 1)
        # -+++++++----------- bouton pour décoder le texte ----------+++++++- #
        self.decodeBut = QPushButton(groupBox)
        self.decodeBut.setStatusTip(
            u"Cliquez sur ce bouton pour décoder le texte compressé.")
        self.decodeBut.setText(u"DÉCODER")
        self.decodeBut.clicked.connect(self.decode_text)
        textGrid.addWidget(self.decodeBut, 4, 1, 1, 1)
        mainGrid.addWidget(groupBox, 0, 0, 1, 1)
        self.setCentralWidget(centralwidget)
        # -+++++++--------------- une barre de statut ---------------+++++++- #
        self.setStatusBar(QStatusBar(self))
        # -+++++++--------------------- le menu ---------------------+++++++- #
        self.fileMenu = QMenu(u"Fichier")
        self.fileMenu.addAction(u"Importer un texte...", self.open_text)
        self.fileMenu.addAction(
            u"Importer un texte encodé...", lambda: self.open_text(True))
        self.fileMenu.addAction(u"Importer un dictionnaire...", self.open_dict)
        self.fileMenu.addAction(u"Enregistrer le dictionnaire...", self.save_dict)
        self.fileMenu.addAction(u"Quitter", self.close)
        self.menuBar().addMenu(self.fileMenu)
        QMetaObject.connectSlotsByName(self)

    def open_text(self, compressed=False):
        """Ouvrir un fichier contenant un texte compressé ou non."""
        fname, _ = QFileDialog.getOpenFileName(self, u'Ouvrir')
        f = open(fname, 'r')
        with f:
            data = f.read()
            if compressed:
                self.compressedText.setText(data)
            else:
                self.orgText.setText(data)

    def open_dict(self):
        """Ouvrir un dictionnaire de codes Huffman."""
        fname, _ = QFileDialog.getOpenFileName(self, u'Ouvrir')
        self.occ = {}
        self.hCodes = {}
        self.aCodes = {}
        self.hCost = {}
        self.aCost = {}
        self.hCodes = create_dict_from_file(fname)
        self.update_codes_table()
        self.logLab.setText(u"Dictionnaire de Huffman importé.")
        return self.hCodes

    def save_dict(self):
        """Enregistrer le dictionnaire de codes Huffman."""
        fname, _ = QFileDialog.getSaveFileName(self, "Enregistrer sous")
        save_dict_to_file(fname, self.hCodes)

    def make_tab_rows(self):
        """Génère le remplissage des lignes du tableau des codes."""
        dictList = [self.occ, self.aCodes, self.hCodes, self.aCost, self.hCost]
        tabList = []
        charList = self.hCodes.keys() if self.hCodes else self.occ.keys()
        for char in charList:
            l = ["'" + char + "'"]
            for dic in dictList:
                try:
                    l.append(dic[char])
                except KeyError:
                    l.append('')
            tabList.append(l)
        return tabList

    def encode_text(self, wizard=True):
        """Encode le texte original."""
        self.text = self.orgText.toPlainText().encode('utf-8')
        if not self.text:
            self.compressedText.setText(u"")
            self.asciiText.setText(u"")
            self.logLab.setText(
                u"<font color=#A52A2A>Rien à compresser.</font>")
            return
        self.occ = {}
        self.tree = ()
        self.hCodes = {}
        self.aCodes = {}
        self.hCost = {}
        self.aCost = {}
        self.hSqueezed = []
        self.aSqueezed = []
        self.stringHSqueezed = ''
        self.stringASqueezed = ''
        if wizard:
            self.launch_wizard(
                EncodeWizard(self),
                u"<font color=#008000>Compression achevée.</font>")
        else:
            self.make_occ()
            self.make_tree()
            self.make_codes()
            self.make_cost()
            self.make_encoded_text()
            self.make_comp()

    def decode_text(self, wizard=True):
        """Décode le texte compressé."""
        self.codeString = str(
            self.compressedText.toPlainText().replace(' ', ''))
        if not self.codeString or not self.hCodes:
            self.orgText.setText(u"")
            self.asciiText.setText(u"")
            if not self.codeString:
                self.logLab.setText(
                    u"<font color=#A52A2A>Rien à décompresser.</font>")
            if not self.hCodes:
                self.logLab.setText(
                    u"<font color=#A52A2A>Dictionnaire indisponible pour la décompression.</font>")
            return
        self.text = ''
        self.stringASqueezed = ''
        if wizard:
            self.launch_wizard(
                DecodeWizard(self),
                u"<font color=#008000>Texte décompressé.</font>")
        else:
            self.make_code_map()
            self.make_decoded_text()

    def launch_wizard(self, wizard, finishString):
        """Lance l'assistant d'en/décodage pour guider l'utilisateur.
        Cache les options inaccessibles pendant l'assistant.
        """
        self.logLab.setText(
            u"<font color=#9E6A00>Opération en cours. "
            u"Suivre les indications.</font>")
        disItems = [self.orgText, self.compressedText, self.encodeBut,
                    self.decodeBut, self.fileMenu.actions()[1],
                    self.fileMenu.actions()[2], self.fileMenu.actions()[3]]
        for item in disItems:
            item.setEnabled(False)
        self.compGroup.setVisible(False)
        self.analysGrid.addWidget(wizard, 0, 0, 1, 1)
        res = wizard.exec_()
        if res:
            self.logLab.setText(finishString)
        else:
            self.logLab.setText(
                u"<font color=#A52A2A>Opération interrompue.</font>")
        for item in disItems:
            item.setEnabled(True)
        self.compGroup.setVisible(True)

    def update_ratio_lab(self):
        """Replace la valeur du label du ratio de compression."""
        if not self.stringASqueezed:
            val = '/'
        else:
            val = (len(self.stringHSqueezed.replace(' ', '')) /
                   float(len(self.stringASqueezed.replace(' ', ''))))
        self.ratioLab.setText(unicode('Taux de compression:  ' + str(val)))

    def update_comp_table(self):
        """Met à jour le tableau de comparaison ASCII VS Huffman."""
        self.compTabASCIIMem.setText(unicode(len(''.join(self.aSqueezed))))
        self.compTabHuffMem.setText(unicode(len(''.join(self.hSqueezed))))
        # entropie ?
        self.compTabASCIIEnt.setText('0')
        self.compTabHuffEnt.setText('0')
        self.compTabASCIIAvg.setText(unicode(8))
        self.compTabHuffAvg.setText(unicode(
            average_code_length(self.hSqueezed)))
        self.compTable.resizeColumnsToContents()

    def update_codes_table(self, hlRow=[]):
        """Met à jour le tableau des codes et surligne les lignes de hlRow."""
        self.codesTableModel.hlRow = hlRow
        self.codesTableModel.emptyTable()
        self.codesTableModel.fillTable(self.make_tab_rows())
        self.codesTable.resizeColumnsToContents()

    def centerAndResize(self):
        """Centre et redimmensionne le widget.""" 
        screen = QDesktopWidget().screenGeometry()
        self.resize(screen.width() / 1.6, screen.height() / 1.4)
        size = self.geometry()
        self.move(
            (screen.width() - size.width()) / 2,
            (screen.height() - size.height()) / 2)

    #===================== METHODS FOR EN/DECODE WIZARDS =====================#
    def make_encode_init(self):
        self.compressedText.setText(unicode(self.stringHSqueezed))
        self.asciiText.setText(unicode(self.stringASqueezed))
        self.orgText.setTextColor(QColor(Qt.darkGreen))
        self.orgText.setText(unicode(self.text.decode('utf-8')))
        self.update_codes_table()

    def make_occ(self):
        self.orgText.setTextColor(QColor(Qt.white))
        self.orgText.setText(unicode(self.text.decode('utf-8')))
        self.occ = occurences(self.text)
        self.update_codes_table([0, 1])

    def make_tree(self):
        self.tree = make_trie(self.occ)
        self.update_codes_table()

    def make_codes(self):
        self.hCodes = make_codes(self.tree, {})
        self.aCodes = make_ascii_codes(self.occ.keys(), {})
        self.update_codes_table([2, 3])

    def make_cost(self):
        self.hCost = tree_cost(self.hCodes, self.occ)
        self.aCost = tree_cost(self.aCodes, self.occ)
        self.update_codes_table([4, 5])

    def make_encoded_text(self):
        self.hSqueezed = squeeze(self.text, self.hCodes)
        self.aSqueezed = squeeze(self.text, self.aCodes)
        self.stringHSqueezed = ' '.join(self.hSqueezed)
        self.stringASqueezed = ' '.join(self.aSqueezed)
        self.compressedText.setTextColor(QColor(Qt.darkGreen))
        self.asciiText.setTextColor(QColor(Qt.darkYellow))
        self.compressedText.setText(unicode(self.stringHSqueezed))
        self.asciiText.setText(unicode(self.stringASqueezed))
        self.update_codes_table()

    def make_comp(self):
        self.compressedText.setTextColor(QColor(Qt.white))
        self.asciiText.setTextColor(QColor(Qt.white))
        self.compressedText.setText(unicode(self.stringHSqueezed))
        self.asciiText.setText(unicode(self.stringASqueezed))
        self.update_codes_table()
        self.update_comp_table()
        self.update_ratio_lab()

    def make_decode_init(self):
        self.orgText.setText(unicode(self.text))
        self.asciiText.setText(unicode(self.stringASqueezed))
        self.compressedText.setTextColor(QColor(Qt.darkGreen))
        self.compressedText.setText(self.compressedText.toPlainText())

    def make_code_map(self):
        self.compressedText.setTextColor(QColor(Qt.white))
        self.compressedText.setText(self.compressedText.toPlainText())
        self.orgText.setText(unicode(self.text))
        self.asciiText.setText(unicode(self.stringASqueezed))
        self.codeMap = dict(zip(self.hCodes.values(), self.hCodes.keys()))
        self.update_codes_table([0, 3])

    def make_decoded_text(self):
        self.unSqueezed = unsqueeze(self.codeString, self.codeMap)
        self.text = ''.join(self.unSqueezed)
        self.orgText.setTextColor(QColor(Qt.darkGreen))
        self.orgText.setText(unicode(self.text.decode('utf-8')))
        self.asciiText.setText(unicode(self.stringASqueezed))
        self.update_codes_table()

    def make_ascii_decode(self):
        self.orgText.setTextColor(QColor(Qt.white))
        self.orgText.setText(unicode(self.text.decode('utf-8')))
        self.aCodes = make_ascii_codes(self.codeMap.values(), {})
        self.aSqueezed = squeeze(self.text, self.aCodes)
        self.stringASqueezed = ' '.join(self.aSqueezed)
        self.occ = occurences(self.text)
        self.hCost = tree_cost(self.hCodes, self.occ)
        self.aCost = tree_cost(self.aCodes, self.occ)
        self.asciiText.setTextColor(QColor(Qt.darkGreen))
        self.asciiText.setText(unicode(self.stringASqueezed))
        self.update_codes_table([1, 2, 4, 5])
예제 #35
0
class PresenceOverviewWidget(HorsePanel):
    @Slot(QModelIndex)
    def cell_entered(self, ndx):
        employee_id = self._employee_id_on_row(ndx)

        if not employee_id:
            self._show_totals_day_off(None)

        elif employee_id:
            chrono.chrono_start()

            employee = None
            for i in self.employees:
                if i.employee_id == employee_id:
                    employee = i
                    break

            self.detail_subframe.set_title(employee.fullname)
            self._show_totals_day_off(employee_id)

            d = date(
                self.base_date.year, self.base_date.month,
                min(
                    calendar.monthrange(self.base_date.year,
                                        self.base_date.month)[1],
                    max(1, ndx.column())))

            chrono.chrono_click("Retrieveing data")
            tars = dao.task_action_report_dao.get_reports_for_employee_id_on_date(
                employee_id, d)
            work_timetracks = dao.timetrack_dao.all_work_for_employee_date_manual(
                employee_id, d)
            presence_timetracks = dao.timetrack_dao.all_presence_for_employee_date_managed_by_code_full(
                employee_id, d)
            # employee = dao.employee_dao.find_by_id(employee_id)
            special_activities = dao.special_activity_dao.find_on_day(
                employee_id, d)

            chrono.chrono_click("Redrawing")
            self.time_report_view.redraw(datetime(d.year, d.month, d.day, 6,
                                                  0),
                                         tars,
                                         employee_id,
                                         work_timetracks,
                                         presence_timetracks,
                                         special_activities,
                                         view_title=_("Work on {}").format(
                                             date_to_dmy(d, full_month=True)))
            session().close(
            )  # FIXME Put his one line above; but that's tough ! SQLA doesn't help us much here !
            chrono.chrono_click("Session closed")

            # for event_type, duration in self.day_event_totals[employee_id].items():
            #     mainlog.debug("{}{}".format(event_type, duration))

        self._toggle_days_off_actions()

    def _employee_id_on_row(self, row_or_ndx):
        r = row_or_ndx
        if type(r) != int:
            r = row_or_ndx.row()

        return self._table_model.data(self._table_model.index(r, 0),
                                      Qt.UserRole)

    DAY_EVENT_PALETTE = {
        DayEventType.holidays: (Qt.GlobalColor.white, Qt.GlobalColor.red),
        DayEventType.day_off: (Qt.GlobalColor.white, Qt.GlobalColor.darkRed),
        DayEventType.unpaid_day_off:
        (Qt.GlobalColor.black, Qt.GlobalColor.magenta),
        DayEventType.free_day:
        (Qt.GlobalColor.white, Qt.GlobalColor.darkMagenta),
        DayEventType.overtime: (Qt.GlobalColor.black, Qt.GlobalColor.green),
        DayEventType.recuperation:
        (Qt.GlobalColor.white, Qt.GlobalColor.darkGreen),
        DayEventType.unemployment: (Qt.GlobalColor.white, Qt.GlobalColor.blue),
        DayEventType.unemployment_short:
        (Qt.GlobalColor.white, Qt.GlobalColor.darkBlue),
        DayEventType.work_accident: (Qt.GlobalColor.black,
                                     Qt.GlobalColor.yellow),
        DayEventType.sick_leave: (Qt.GlobalColor.white,
                                  Qt.GlobalColor.darkYellow)
    }

    MONTH_EVENT_COLUMN = 2
    YEAR_EVENT_COLUMN = 3

    def _make_total_days_off_panel(self):

        widget = QFrame()
        widget.setObjectName('HorseRegularFrame')

        widget.setFrameShape(QFrame.Panel)
        widget.setFrameShadow(QFrame.Sunken)
        layout = QVBoxLayout()

        #layout.addWidget(QLabel(_("Days off to date")))
        self.day_off_total_duration_labels = dict()
        self.day_off_month_duration_labels = dict()
        self.day_off_labels = dict()

        self._day_off_table_model = QStandardItemModel(10, 3)
        self._day_off_table_model.setHorizontalHeaderLabels(
            [None, None, _("This\nmonth"),
             _("Before")])
        self.day_off_table_view = QTableView(None)
        self.day_off_table_view.setModel(self._day_off_table_model)

        # self.day_off_table_view.setHorizontalHeader(self.headers_view)
        self.day_off_table_view.verticalHeader().hide()
        self.day_off_table_view.setAlternatingRowColors(True)
        self.day_off_table_view.setEditTriggers(
            QAbstractItemView.NoEditTriggers)

        self.day_off_table_view.hide()

        row = 0
        for det in DayEventType.symbols():
            ndx = self._day_off_table_model.index(row, 0)
            self._day_off_table_model.setData(ndx, det.description,
                                              Qt.DisplayRole)

            ndx = self._day_off_table_model.index(row, 1)
            fg, bg = self.DAY_EVENT_PALETTE[det]
            self._day_off_table_model.setData(ndx, QBrush(bg),
                                              Qt.BackgroundRole)
            self._day_off_table_model.setData(ndx, QBrush(fg),
                                              Qt.TextColorRole)
            self._day_off_table_model.setData(ndx,
                                              DayEventType.short_code(det),
                                              Qt.DisplayRole)

            row += 1

        layout.addWidget(self.day_off_table_view)

        grid = QGridLayout()
        self.days_off_layout = grid
        grid.setColumnStretch(3, 1)
        row = 0

        grid.addWidget(QLabel(_('Year')), row, self.YEAR_EVENT_COLUMN)
        grid.addWidget(QLabel(_('Month')), row, self.MONTH_EVENT_COLUMN)
        row += 1

        for det in DayEventType.symbols():
            self.day_off_total_duration_labels[det] = QLabel("-")
            self.day_off_month_duration_labels[det] = QLabel("-")
            self.day_off_labels[det] = QLabel(det.description)

            hlayout = QHBoxLayout()

            sl = QLabel()
            fg, bg = self.DAY_EVENT_PALETTE[det]

            def to_html_rgb(color):
                i = color.red() * 256 * 256 + color.green() * 256 + color.blue(
                )
                return "#{:06X}".format(i)

            p = QPalette()
            p.setColor(QPalette.Window, QColor(bg))
            p.setColor(QPalette.WindowText, QColor(fg))
            sl.setPalette(p)
            sl.setAlignment(Qt.AlignCenter)
            sl.setStyleSheet("border: 2px solid black; background: {}".format(
                to_html_rgb(QColor(bg))))

            t = DayEventType.short_code(det)
            mainlog.debug(t)
            sl.setAutoFillBackground(True)
            sl.setText(t)

            grid.addWidget(sl, row, 0)
            grid.addWidget(self.day_off_labels[det], row, 1)
            grid.addWidget(self.day_off_total_duration_labels[det], row,
                           self.YEAR_EVENT_COLUMN)
            grid.addWidget(self.day_off_month_duration_labels[det], row,
                           self.MONTH_EVENT_COLUMN)

            hlayout.addStretch()

            row += 1

        layout.addLayout(grid)
        layout.addStretch()

        self.day_off_table_view.resizeColumnsToContents()
        # self.day_off_table_view.setMinimumWidth( self.day_off_table_view.width())
        # self.day_off_table_view.resize( self.day_off_table_view.minimumWidth(),
        #                                 self.day_off_table_view.minimumHeight(),)

        widget.setLayout(layout)
        return widget

    def _show_totals_day_off(self, employee_id):

        mainlog.debug("_show_totals_day_off : {}".format(employee_id))

        def form_layout_row_set_visible(layout, row_ndx, is_visible):
            for i in range(layout.columnCount()):
                l = layout.itemAtPosition(row_ndx, i)
                if l and l.widget():
                    l.widget().setVisible(is_visible)

        det_to_show = dict()

        row = 0
        for det in DayEventType.symbols():

            yearly = 0
            if employee_id in self.all_events_in_year:
                if det in self.all_events_in_year[employee_id]:
                    yearly = nice_round(
                        self.all_events_in_year[employee_id][det])

            monthly = 0
            if employee_id in self.day_event_totals:
                if det in self.day_event_totals[employee_id]:
                    monthly = nice_round(
                        self.day_event_totals[employee_id][det])

                # ndx = self._day_off_table_model.index(row,self.YEAR_EVENT_COLUMN)
                # self._day_off_table_model.setData(ndx, v, Qt.DisplayRole)

            if yearly or monthly:
                det_to_show[det] = {'monthly': monthly, 'yearly': yearly}

        if det_to_show:
            # If there are some days spent on some counters, then we display
            # those counters *only*
            mainlog.debug("_show_totals_day_off : showing some events ".format(
                str(det_to_show)))
            row = 0
            for det in DayEventType.symbols():
                if det in det_to_show:
                    monthly = det_to_show[det]['monthly']
                    yearly = det_to_show[det]['yearly']
                    form_layout_row_set_visible(self.days_off_layout, row + 1,
                                                True)
                    self.day_off_total_duration_labels[det].setText(yearly
                                                                    or '-')
                    self.day_off_month_duration_labels[det].setText(monthly
                                                                    or '-')
                else:
                    form_layout_row_set_visible(self.days_off_layout, row + 1,
                                                False)
        else:
            # If there are no days spent on any counter, then we display
            # all counters at the 0 mark.
            mainlog.debug("_show_totals_day_off : showing no event")
            row = 0
            for det in DayEventType.symbols():
                form_layout_row_set_visible(self.days_off_layout, row + 1,
                                            True)
                row += 1

        # self.day_off_table_view.resizeColumnsToContents()

        self.days_off_panel.parent().update()

    @Slot()
    def refresh_action(self):
        global dao

        # mainlog.debug("refresh action started")
        self.hours_per_pers_subframe.set_title(date_to_my(
            self.base_date, True))

        chrono.chrono_start()
        all_events_in_month = people_admin_service.events_for_month(
            self.base_date)

        employee_with_events = [
            event.employee_id for event in all_events_in_month
        ]

        # mainlog.debug(all_events_in_month)

        self.all_events_in_year = people_admin_service.events_for_year(
            self.base_date.year)
        self.all_presences = all_presences = dao.employee_dao.presence_overview_for_month(
            self.base_date)

        all_correction_times = dict()
        for s in dao.month_time_synthesis_dao.load_all_synthesis(
                self.base_date.year, self.base_date.month):
            all_correction_times[s.employee_id] = s.correction_time

        special_activities = dao.special_activity_dao.find_on_month(
            self.base_date)

        employees = list(
            filter(
                lambda e: e.is_active or e.employee_id in all_presences or e.
                employee_id in all_correction_times or e.employee_id in
                special_activities or e.employee_id in employee_with_events,
                dao.employee_dao.list_overview()))
        self.employees = employees

        chrono.chrono_click()

        day_max = calendar.monthrange(self.base_date.year,
                                      self.base_date.month)[1]
        t_start = datetime(self.base_date.year, self.base_date.month, 1)
        t_end = datetime(self.base_date.year, self.base_date.month, day_max,
                         23, 59, 59, 999999)

        self._table_model.setRowCount(len(employees))
        self._table_model.setColumnCount(1 + day_max + 3)

        headers = QStandardItemModel(1, 1 + day_max + 3)

        headers.setHeaderData(0, Qt.Orientation.Horizontal, _("Employee"))
        for i in range(day_max):
            headers.setHeaderData(i + 1, Qt.Orientation.Horizontal,
                                  "{}".format(i + 1))
        headers.setHeaderData(day_max + 1, Qt.Orientation.Horizontal,
                              _("Correction"))
        headers.setHeaderData(day_max + 2, Qt.Orientation.Horizontal,
                              _("Total"))
        headers.setHeaderData(day_max + 3, Qt.Orientation.Horizontal,
                              _("Days off"))

        self.headers_view.setModel(
            headers)  # qt's doc : The view does *not* take ownership
        self.header_model = headers
        self.headers_view.setModel(
            self.header_model)  # qt's doc : The view does *not* take ownership

        # Compute all mondays indices
        monday = 0
        if t_start.weekday() > 0:
            monday = 7 - t_start.weekday()
        all_mondays = []

        while monday < day_max:
            all_mondays.append(monday)
            monday += 7

        today = date.today()

        # mainlog.debug("Running on employees")
        for row in range(self._table_model.rowCount()):

            # Clear the line
            for col in range(0, 32):
                ndx = self._table_model.index(row, col)
                self._table_model.setData(ndx, None, Qt.BackgroundRole)
                self._table_model.setData(ndx, QBrush(Qt.GlobalColor.black),
                                          Qt.TextColorRole)
                self._table_model.setData(ndx, None, Qt.DisplayRole)
                self._table_model.setData(ndx, None, Qt.UserRole)
                self._table_model.setData(ndx, None, Qt.UserRole + 1)
                #     else:
                #         self._table_model.setData(ndx,None,Qt.BackgroundRole)

                # else:
                #     self._table_model.setData(ndx,None,Qt.DisplayRole)
                #     self._table_model.setData(ndx,None,Qt.BackgroundRole)

            # Mark mondays
            for col in all_mondays:
                # col + 1 to account for the employee column
                self._table_model.setData(
                    self._table_model.index(row, col + 1),
                    QBrush(QColor(230, 230, 255)), Qt.BackgroundRole)

            # Mark today
            if today.month == self.base_date.month and today.year == self.base_date.year:
                self._table_model.setData(
                    self._table_model.index(row, today.day),
                    QBrush(QColor(255, 255, 128)), Qt.BackgroundRole)

        row = 0
        for employee in employees:  # employees are sorted

            self._table_model.setData(self._table_model.index(row, 0),
                                      employee.fullname,
                                      Qt.DisplayRole)  # FIXME Use a delegate
            self._table_model.setData(self._table_model.index(row, 0),
                                      employee.employee_id,
                                      Qt.UserRole)  # FIXME Use a delegate

            correction = 0
            if employee.employee_id in all_correction_times:
                correction = all_correction_times[employee.employee_id]
                self._table_model.setData(
                    self._table_model.index(row, day_max + 1),
                    duration_to_hm(correction, short_unit=True),
                    Qt.DisplayRole)
            else:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 1), None,
                    Qt.DisplayRole)

            presence = 0
            if employee.employee_id in all_presences and len(
                    all_presences[employee.employee_id]) > 0:
                import functools
                presence = functools.reduce(
                    lambda acc, s: acc + s,
                    all_presences[employee.employee_id], 0)
            presence += correction

            if presence != 0:
                self._table_model.setData(ndx, QBrush(Qt.GlobalColor.black),
                                          Qt.TextColorRole)
                self._table_model.setData(
                    self._table_model.index(row, day_max + 2),
                    duration_to_hm(presence, short_unit=True), Qt.DisplayRole)
            else:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 2), None,
                    Qt.DisplayRole)

            if employee.employee_id in all_presences and len(
                    all_presences[employee.employee_id]) > 0:
                for b in range(len(all_presences[employee.employee_id])):
                    ndx = self._table_model.index(row, b + 1)

                    p = all_presences[employee.employee_id][b]

                    if p > 0:
                        self._table_model.setData(
                            ndx, duration_to_hm(p, short_unit=True),
                            Qt.DisplayRole)
                        self._table_model.setData(ndx, p, Qt.UserRole)

                        if p >= 4 and p <= 8:
                            # Regular work load
                            self._table_model.setData(
                                ndx, QBrush(QColor(192, 255, 192)),
                                Qt.BackgroundRole)
                        elif p > 8 or (p < 4 and p > 0):
                            # Problematic work load
                            self._table_model.setData(
                                ndx, QBrush(QColor(255, 192, 192)),
                                Qt.BackgroundRole)

            if employee.employee_id in special_activities:
                sa_of_employee = special_activities[employee.employee_id]

                for sa in sa_of_employee:
                    start = max(t_start, sa.start_time)
                    end = min(t_end, sa.end_time)

                    for i in range(start.day, end.day + 1):
                        ndx = self._table_model.index(row, i)
                        self._table_model.setData(ndx,
                                                  QBrush(QColor(255, 128, 0)),
                                                  Qt.BackgroundRole)

                # self._table_model.setData(self._table_model.index(row,b+1),Qt.AlignRight | Qt.AlignVCenter,Qt.TextAlignmentRole)
            row += 1

        # Display day events

        employee_id_to_row = dict()  # little accelerator
        for row in range(len(employees)):
            employee_id_to_row[employees[row].employee_id] = row

        # Compute days off totals and show them

        self.day_event_totals = dict([(e.employee_id, dict())
                                      for e in employees])
        for day_event in all_events_in_month:
            # mainlog.debug("employee_id = {}".format(day_event.employee_id))
            # if day_event.employee_id not in self.day_event_totals:
            #    mainlog.debug(self.day_event_totals)

            t = self.day_event_totals[day_event.employee_id]
            if day_event.event_type not in t:
                t[day_event.event_type] = day_event.duration
            else:
                t[day_event.event_type] += day_event.duration

        for employee in employees:  # employees are sorted
            t = self.day_event_totals[employee.employee_id]
            mainlog.debug(t)
            total_off = sum(t.values())
            mainlog.debug(total_off)
            row = employee_id_to_row[employee.employee_id]
            mainlog.debug(row)
            if total_off:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 3),
                    nice_round(total_off), Qt.DisplayRole)
            else:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 3), None,
                    Qt.DisplayRole)

        # Show days off

        for day_event in all_events_in_month:
            row = employee_id_to_row[day_event.employee_id]
            col = day_event.date.day

            fg = bg = None
            if day_event.event_type in self.DAY_EVENT_PALETTE:
                fg, bg = self.DAY_EVENT_PALETTE[day_event.event_type]
            else:
                fg, bg = Qt.GlobalColor.red, Qt.GlobalColor.gray

            ndx = self._table_model.index(row, col)

            self._table_model.setData(ndx, day_event.day_event_id,
                                      Qt.UserRole + 1)

            # The problem here is to nicely blend the fact
            # that you can have a day event mixed with actual work
            # the very same day. Here's a poor man solution.

            active_time = self._table_model.data(ndx, Qt.UserRole)
            if not active_time:
                self._table_model.setData(
                    ndx, DayEventType.short_code(day_event.event_type),
                    Qt.DisplayRole)

                self._table_model.setData(ndx, QBrush(fg), Qt.TextColorRole)
                self._table_model.setData(ndx, QBrush(bg), Qt.BackgroundRole)
            else:
                self._table_model.setData(ndx, QBrush(fg), Qt.TextColorRole)
                self._table_model.setData(ndx, QBrush(bg), Qt.BackgroundRole)

                self._table_model.setData(
                    ndx,
                    duration_to_hm(active_time, short_unit=True) +
                    DayEventType.short_code(day_event.event_type),
                    Qt.DisplayRole)

        chrono.chrono_click()

        #for i in range(len(all_mondays)):
        self.table_view.resizeColumnsToContents()

        # mainlog.debug("Reset selection")
        ndx = self.table_view.currentIndex()

        self.table_view.selectionModel().clear()
        # self.table_view.selectionModel().clearSelection()
        # self.table_view.selectionModel().select( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select)
        # self.table_view.selectionModel().select( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select)
        self.table_view.selectionModel().setCurrentIndex(
            self.table_view.model().index(ndx.row(), ndx.column()),
            QItemSelectionModel.Select)

        self.cell_entered(self.table_view.currentIndex())

    @Slot()
    def edit_tars(self):

        employee_id = self._employee_id_on_row(self.table_view.currentIndex())

        d = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1],
                max(1, ndx.column())))

        dialog = TimeReportingScannerDialog(self)
        dialog.set_data(datetime(d.year, d.month, d.day, 6, 0), employee_id)
        dialog.exec_()

        if dialog.result() == QDialog.Accepted:
            # pub.sendMessage('time_report.changed')
            self.timetrack_changed.emit()
            self.refresh_action()

    @Slot()
    def show_actions(self):
        button = self.action_menu.parent()
        p = button.mapToGlobal(QPoint(0, button.height()))
        self.action_menu.exec_(p)

    @Slot()
    def delete_holidays(self):
        ndx = self.table_view.currentIndex()
        employee_id = self._employee_id_on_row(ndx)
        d = date(self.base_date.year, self.base_date.month, ndx.column())

        if dao.special_activity_dao.delete_by_employee_and_date(
                employee_id, d):
            self.refresh_panel()

    @Slot()
    def create_holidays(self):
        employee_id = self._employee_id_on_row(self.table_view.currentIndex())

        left_col = 1000
        right_col = 0
        for ndx in self.table_view.selectionModel().selectedIndexes():
            c = ndx.column()
            left_col = min(c, left_col)
            right_col = max(c, right_col)

        d_start = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1], max(1,
                                                                  left_col)))

        d_end = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1],
                max(1, right_col)))

        dialog = HolidaysDialog(self)

        sa = SpecialActivity()
        sa.employee_id = employee_id
        sa.reporter_id = user_session.user_id
        sa.encoding_date = date.today()
        sa.start_time = datetime(d_start.year, d_start.month, d_start.day, 6,
                                 0)
        sa.end_time = datetime(d_end.year, d_end.month, d_end.day, 14, 0)

        dialog.setup(sa, dao.employee_dao.find_by_id(employee_id).fullname)

        # dialog.set_data(employee,self.base_date,c)
        dialog.exec_()
        if dialog.result() == QDialog.Accepted:
            dao.special_activity_dao.save(sa)
            self.refresh_action()

    @Slot()
    def edit_month_correction(self):
        employee_id = self._employee_id_on_row(self.table_view.currentIndex())

        if employee_id:
            employee = dao.employee_dao.find_by_id(employee_id)
            c = dao.month_time_synthesis_dao.load_correction_time(
                employee_id, self.base_date.year, self.base_date.month)

            dialog = MonthTimeCorrectionDialog(self)
            dialog.set_data(employee.fullname, self.base_date, c)
            dialog.exec_()
            if dialog.result() == QDialog.Accepted:
                c = dao.month_time_synthesis_dao.save(employee_id,
                                                      self.base_date.year,
                                                      self.base_date.month,
                                                      dialog.correction_time)
                self.refresh_action()

    @Slot()
    def month_today(self):
        self.base_date = date.today()
        self.refresh_action()

    @Slot()
    def month_before(self):
        m = self.base_date.month

        if m > 1:
            self.base_date = date(self.base_date.year, m - 1, 1)
        else:
            self.base_date = date(self.base_date.year - 1, 12, 1)
        self.refresh_action()

    @Slot()
    def month_after(self):
        m = self.base_date.month

        if self.base_date.year < date.today().year + 1 \
                or m < date.today().month:
            if m < 12:
                self.base_date = date(self.base_date.year, m + 1, 1)
            else:
                self.base_date = date(self.base_date.year + 1, 1, 1)
            self.refresh_action()

    @Slot()
    def edit_timetrack_no_ndx(self):
        ndx = self.table_view.currentIndex()
        if ndx.isValid() and ndx.column() >= 0 and ndx.row() >= 0:
            self.edit_timetrack(ndx)
        else:
            showWarningBox(_("Can't edit"),
                           _("You must first select a day/person."))

    timetrack_changed = Signal()

    @Slot(QModelIndex)
    def edit_timetrack(self, ndx):
        global dao
        global user_session

        if ndx.column() >= 1:
            edit_date = date(
                self.base_date.year, self.base_date.month,
                ndx.column())  # +1 already in because of employee's names
            employee_id = self._employee_id_on_row(ndx)

            tars = dao.task_action_report_dao.get_reports_for_employee_id_on_date(
                employee_id, edit_date)

            if len(tars) == 0:

                d = EditTimeTracksDialog(self, dao, edit_date)
                d.set_employee_and_date(employee_id, edit_date)
                d.exec_()
                if d.result() == QDialog.Accepted:
                    self.refresh_action()
                    self.timetrack_changed.emit()
                d.deleteLater()

            else:
                edit_date = datetime(self.base_date.year,
                                     self.base_date.month,
                                     ndx.column(),
                                     hour=6)
                from koi.TimeReportingScanner import TimeReportingScannerDialog
                d = TimeReportingScannerDialog(self)
                d.set_data(edit_date, employee_id)  # or 16
                d.exec_()
                if d.result() == QDialog.Accepted:
                    self.refresh_action()
                    self.timetrack_changed.emit()
                d.deleteLater()

    @Slot()
    def editTaskActionReports(self):
        if not user_session.has_any_roles(['TimeTrackModify']):
            return

        m = self.base_date.month
        ndx = self.table_view.currentIndex()

        if ndx.isValid() and ndx.column() >= 0 and ndx.row() >= 0:
            edit_date = date(
                self.base_date.year, m,
                ndx.column())  # +1 already in because of employee's names
            employee = self._table_model.data(
                self._table_model.index(ndx.row(), 0),
                Qt.UserRole)  # FIXME Use a delegate

            d = EditTaskActionReportsDialog(dao, self, edit_date)
            d.set_employee_date(employee, edit_date)
            d.exec_()
            if d.result() == QDialog.Accepted:
                self.refresh_action()
            d.deleteLater()
        else:
            showWarningBox(_("Can't edit"),
                           _("You must first select a day/person."))

    # @Slot(QModelIndex)
    # def timetrack_changed(self,ndx):

    #     selected_timetrack = self.controller.model.object_at(ndx)

    #     # Update the colors in the timetrack views
    #     # to show what action reports correspond to the
    #     # selected timetrack

    #     self.controller_actions.model.current_timetrack = selected_timetrack
    #     self.controller_actions.model.beginResetModel()
    #     self.controller_actions.model.endResetModel()

    #     # Make sure the first of the action reports is shown in the
    #     # table

    #     action_reports = self.controller_actions.model.objects
    #     for i in range(len(action_reports)-1,-1,-1):
    #         if action_reports[i] and action_reports[i].timetrack == selected_timetrack:
    #             self.controller_actions.view.scrollTo(self.controller_actions.model.index(i,0))
    #             break

    def _make_table_header(self):
        pass

    def __init__(self, parent, find_order_action_slot):
        super(PresenceOverviewWidget, self).__init__(parent)

        self.set_panel_title(_("Presence overview"))
        self.base_date = date.today()

        headers = QStandardItemModel(1, 31 + 3)
        self._table_model = QStandardItemModel(1, 31 + 3, None)

        self.headers_view = QHeaderView(Qt.Orientation.Horizontal, self)
        self.header_model = headers
        self.headers_view.setResizeMode(QHeaderView.ResizeToContents)
        self.headers_view.setModel(
            self.header_model)  # qt's doc : The view does *not* take ownership

        self.table_view = TableViewSignaledEvents(None)
        self.table_view.setModel(self._table_model)

        self.table_view.setHorizontalHeader(self.headers_view)
        self.table_view.verticalHeader().hide()
        self.table_view.setAlternatingRowColors(True)
        self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.table_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table_view.customContextMenuRequested.connect(
            self.popup_context_menu)

        self.copy_action = QAction(_("Copy order parts"), self.table_view)
        self.copy_action.triggered.connect(self.copy_slot)
        self.copy_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_C))
        self.copy_action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        self.table_view.addAction(self.copy_action)

        self.select_all_action = QAction(_("Select all"), self.table_view)
        self.select_all_action.triggered.connect(self.select_all_slot)
        self.select_all_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_A))
        self.select_all_action.setShortcutContext(
            Qt.WidgetWithChildrenShortcut)
        self.table_view.addAction(self.select_all_action)

        # self.table_view.setSelectionBehavior(QAbstractItemView.SelectItems)
        # self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)

        navbar = NavBar(self, [(_("Month before"), self.month_before),
                               (_("Today"), self.month_today),
                               (_("Action"), self.show_actions),
                               (_("Month after"), self.month_after),
                               (_("Find"), find_order_action_slot)])

        self.action_menu = QMenu(navbar.buttons[2])
        navbar.buttons[2].setObjectName("specialMenuButton")
        navbar.buttons[4].setObjectName("specialMenuButton")

        self._make_days_off_menu_and_action_group()

        list_actions = [  # (_("Edit"),self.edit_tars, None, None),
            (_("Edit"), self.edit_timetrack_no_ndx, None, None),
            (_("Month correction"), self.edit_month_correction, None,
             [RoleType.modify_monthly_time_track_correction]),
            (self.days_off_menu, None), (self.copy_action, None),
            (self.select_all_action, None)
        ]

        # (_("Insert holidays"),self.create_holidays, None, None),
        # (_("Delete holidays"),self.delete_holidays, None, None) ]

        populate_menu(self.action_menu, self, list_actions)

        # mainlog.debug("tile widget")
        self.title_box = TitleWidget(_("Presence Overview"), self, navbar)
        self.vlayout = QVBoxLayout(self)
        self.vlayout.setObjectName("Vlayout")
        self.vlayout.addWidget(self.title_box)

        self.hours_per_pers_subframe = SubFrame(_("Overview"), self.table_view,
                                                self)
        self.vlayout.addWidget(self.hours_per_pers_subframe)

        self.time_report_view = TimeReportView(self)

        self.days_off_panel = self._make_total_days_off_panel()
        vbox = QVBoxLayout()
        vbox.addWidget(self.days_off_panel)
        vbox.addStretch()
        vbox.setStretch(0, 0)
        vbox.setStretch(1, 1)

        hlayout = QHBoxLayout()
        hlayout.addWidget(self.time_report_view)
        hlayout.addLayout(vbox)
        hlayout.setStretch(0, 1)
        self.detail_subframe = SubFrame(_("Day"), hlayout, self)

        self.vlayout.addWidget(self.detail_subframe)

        self.setLayout(self.vlayout)

        # dbox = QVBoxLayout()
        # dbox.addWidget(QLabel("kjkljkj"))

        # self.total_active_hours = LabeledValue(_("Total activity"))
        # dbox.addWidget(self.total_active_hours)

        # hbox = QHBoxLayout()
        # hbox.addWidget(self.table_view)
        # hbox.addLayout(dbox)

        # self.selection_model = self.table_view.selectionModel()
        # mainlog.debug(m)
        #sm = QItemSelectionModel(self.table_view.model())
        #sm.setModel(self.table_view.model())
        # self.table_view.setSelectionModel(self.selection_model)

        self.table_view.selectionModel().currentChanged.connect(
            self.cell_entered)

        self.table_view.doubleClickedCell.connect(self.edit_timetrack)

    def _selection_to_period(self):
        left_col = 1000
        right_col = 0
        for ndx in self.table_view.selectionModel().selectedIndexes():
            c = ndx.column()
            left_col = min(c, left_col)
            right_col = max(c, right_col)

        d_start = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1], max(1,
                                                                  left_col)))

        d_end = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1],
                max(1, right_col)))

        return d_start, d_end

    def _toggle_days_off_actions(self):
        day_max = calendar.monthrange(self.base_date.year,
                                      self.base_date.month)[1]

        ndx = self.table_view.currentIndex()

        can_add = can_remove = False

        if ndx.column() >= 1 and ndx.column() <= day_max:

            day_event_id = ndx.data(Qt.UserRole + 1)

            can_add = True

            # if not day_event_id:
            #     day = ndx.column() - 1
            #
            #     employee_id = self._employee_id_on_row(ndx)
            #     if employee_id in self.all_presences:
            #         if not self.all_presences[employee_id][day]:
            #             can_add = True
            #         else:
            #             can_add = True
            #     else:
            #         can_add = True

            can_remove = day_event_id is not None

        self.days_off_add_submenu.setEnabled(can_add)
        for actions in self.days_off_action_group.actions():
            actions.setEnabled(can_add)

        self.day_off_remove_action.setEnabled(can_remove)

    def _add_day_off(self, action):

        if action.data() != 'Remove':

            day_event_type, day_event_duration = action.data()
            day_event_type = DayEventType.from_str(day_event_type)

            mainlog.debug("selected action {} {}".format(
                day_event_type, day_event_duration))

            ndx = self.table_view.currentIndex()
            day_event_id = ndx.data(Qt.UserRole + 1)

            # if day_event_id:
            #     showWarningBox(_("There's already a day off here"))
            #     return

            employee_id = self._employee_id_on_row(ndx)
            if employee_id in self.all_presences:
                day = ndx.column() - 1
                mainlog.debug("_add_day_off : employee_id={}, day={}".format(
                    employee_id, day))
                mainlog.debug(self.all_presences[employee_id])
                mainlog.debug(type(self.all_presences[employee_id]))

                # if self.all_presences[employee_id][day]:
                #     showWarningBox(_("One can't add day off where there is activity"))
                #     return
            else:
                mainlog.debug(
                    "_add_day_off : employee_id={} not yet known".format(
                        employee_id))

            day_event = DayEvent()
            day_event.employee_id = employee_id
            day_event.event_type = day_event_type

            day, last_day = self._selection_to_period()

            if day_event_duration in (0.5, 1):
                days_durations = [(day, day_event_duration)]
            else:
                days_durations = []
                day, last_day = self._selection_to_period()
                while day <= last_day:
                    days_durations.append(
                        (day, 1))  # One full work day on the day
                    day += timedelta(1)

            # mainlog.debug(days_durations)
            mainlog.debug("Creating day event of type {}".format(
                day_event.event_type))

            try:
                people_admin_service.set_event_on_days(day_event,
                                                       days_durations)
            except ServerException as ex:
                showErrorBox(ex.translated_message)

            self.refresh_action()

    def _remove_day_off(self):
        # Grab all the selected events

        event_ids = []
        for ndx in self.table_view.selectionModel().selectedIndexes():
            day_event_id = ndx.data(Qt.UserRole + 1)
            if day_event_id:
                mainlog.debug("Removing event: {}".format(day_event_id))
                event_ids.append(day_event_id)

        # Remove them

        if event_ids:
            people_admin_service.remove_events(event_ids)
            self.refresh_action()

    def _make_days_off_menu_and_action_group(self):
        # We use a action group to be able to use the data() of actions
        # when action is tigerred

        # Call this ONLY ONCE because there are signal/slot connections.

        self.days_off_menu = QMenu(_("Day off"))
        self.days_off_add_submenu = QMenu(_("Set day off"))
        self.days_off_action_group = QActionGroup(self)

        for det in DayEventType.symbols():
            a_one = QAction(_("Set one day"), self.days_off_action_group)
            a_one.setData((det.value, 1))

            a_half = QAction(_("Set half day"), self.days_off_action_group)
            a_half.setData((det.value, 0.5))

            a_period = QAction(_("Set period"), self.days_off_action_group)
            a_period.setData((det.value, 2))

            self.days_off_action_group.addAction(a_one)
            self.days_off_action_group.addAction(a_half)
            self.days_off_action_group.addAction(a_period)

            m = QMenu(_("Set time off for {}").format(det.description))
            m.addAction(a_one)
            m.addAction(a_half)
            m.addAction(a_period)
            self.days_off_add_submenu.addMenu(m)

        self.days_off_action_group.triggered.connect(self._add_day_off)

        self.day_off_remove_action = QAction(_("Remove day off"), self)
        self.day_off_remove_action.triggered.connect(self._remove_day_off)

        # Now we have the actions, we build the menu

        self.days_off_menu.addMenu(self.days_off_add_submenu)
        self.days_off_menu.addAction(self.day_off_remove_action)

    @Slot(QPoint)
    def popup_context_menu(self, position):
        self.days_off_menu.exec_(QCursor.pos())

    @Slot()
    def select_all_slot(self):
        m = self.table_view.model()
        all = QItemSelection(m.index(0, 0),
                             m.index(m.rowCount() - 1,
                                     m.columnCount() - 1))
        self.table_view.selectionModel().select(all,
                                                QItemSelectionModel.Select)

    @Slot()
    def copy_slot(self):

        # Collect the rows indices

        indices = self.table_view.selectedIndexes()

        if not indices:
            return

        min_row = max_row = indices[0].row()
        min_col = max_col = indices[0].column()

        def min_max(minimum, v, maximum):
            if v < minimum:
                return v, maximum
            elif v > maximum:
                return minimum, v
            else:
                return minimum, maximum

        for ndx in self.table_view.selectedIndexes():
            min_row, max_row = min_max(min_row, ndx.row(), max_row)
            min_col, max_col = min_max(min_col, ndx.column(), max_col)

        mainlog.debug("Copy from {},{} to {},{}".format(
            min_row, min_col, max_row, max_col))

        day_max = calendar.monthrange(self.base_date.year,
                                      self.base_date.month)[1]

        s = ""
        for r in range(min_row, max_row + 1):
            d = []
            for c in range(min_col, max_col + 1):
                ndx = self._table_model.item(r, c)

                if c == 0 or c > day_max:
                    d.append(ndx.data(Qt.DisplayRole) or "")
                else:
                    t = ndx.data(Qt.UserRole + 1)  # Day off
                    if t:
                        t = ndx.data(Qt.DisplayRole)
                    else:
                        hours = ndx.data(Qt.UserRole)  # Activity hours
                        if hours is not None:
                            t = str(hours).replace('.', ',')
                        else:
                            t = ""

                    d.append(t)

            s += "\t".join(d) + u"\n"

        QApplication.clipboard().setText(s)
예제 #36
0
class RunnerDialog(QDialog):

    options_added = Signal(Options)
    options_running = Signal(Options)
    options_simulated = Signal(Options)
    options_error = Signal(Options, Exception)
    results_saved = Signal(Results, str)
    results_error = Signal(Results, Exception)

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Runner')
        self.setMinimumWidth(750)

        # Runner
        self._runner = None

        self._running_timer = QTimer()
        self._running_timer.setInterval(500)

        # Widgets
        self._dlg_progress = QProgressDialog()
        self._dlg_progress.setRange(0, 100)
        self._dlg_progress.setModal(True)
        self._dlg_progress.hide()

        lbl_outputdir = QLabel("Output directory")
        self._txt_outputdir = DirBrowseWidget()

        max_workers = cpu_count() #@UndefinedVariable
        lbl_workers = QLabel('Number of workers')
        self._spn_workers = QSpinBox()
        self._spn_workers.setRange(1, max_workers)
        self._spn_workers.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        lbl_max_workers = QLabel('(max: %i)' % max_workers)

        self._chk_overwrite = QCheckBox("Overwrite existing results in output directory")
        self._chk_overwrite.setChecked(True)

        self._lbl_available = QLabel('Available')
        self._lst_available = QListView()
        self._lst_available.setModel(_AvailableOptionsListModel())
        self._lst_available.setSelectionMode(QListView.SelectionMode.MultiSelection)

        tlb_available = QToolBar()
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        tlb_available.addWidget(spacer)
        act_open = tlb_available.addAction(getIcon("document-open"), "Open")
        act_open.setShortcut(QKeySequence.Open)
        tlb_available.addSeparator()
        act_remove = tlb_available.addAction(getIcon("list-remove"), "Remove")
        act_clear = tlb_available.addAction(getIcon("edit-clear"), "Clear")

        self._btn_addtoqueue = QPushButton(getIcon("go-next"), "")
        self._btn_addtoqueue.setToolTip("Add to queue")
        self._btn_addtoqueue.setEnabled(False)

        self._btn_addalltoqueue = QPushButton(getIcon("go-last"), "")
        self._btn_addalltoqueue.setToolTip("Add all to queue")
        self._btn_addalltoqueue.setEnabled(False)

        self._lbl_options = QLabel('Queued/Running/Completed')
        self._tbl_options = QTableView()
        self._tbl_options.setModel(_StateOptionsTableModel())
        self._tbl_options.setItemDelegate(_StateOptionsItemDelegate())
        self._tbl_options.setSelectionMode(QListView.SelectionMode.NoSelection)
        self._tbl_options.setColumnWidth(1, 60)
        self._tbl_options.setColumnWidth(2, 80)
        header = self._tbl_options.horizontalHeader()
        header.setResizeMode(0, QHeaderView.Interactive)
        header.setResizeMode(1, QHeaderView.Fixed)
        header.setResizeMode(2, QHeaderView.Fixed)
        header.setResizeMode(3, QHeaderView.Stretch)

        self._btn_start = QPushButton(getIcon("media-playback-start"), "Start")

        self._btn_cancel = QPushButton("Cancel")
        self._btn_cancel.setEnabled(False)

        self._btn_close = QPushButton("Close")

        self._btn_import = QPushButton("Import")
        self._btn_import.setEnabled(False)

        # Layouts
        layout = QVBoxLayout()

        sublayout = QGridLayout()
        sublayout.addWidget(lbl_outputdir, 0, 0)
        sublayout.addWidget(self._txt_outputdir, 0, 1)
        sublayout.addWidget(lbl_workers, 1, 0)

        subsublayout = QHBoxLayout()
        subsublayout.addWidget(self._spn_workers)
        subsublayout.addWidget(lbl_max_workers)
        sublayout.addLayout(subsublayout, 1, 1)
        layout.addLayout(sublayout)

        sublayout.addWidget(self._chk_overwrite, 2, 0, 1, 3)

        sublayout = QGridLayout()
        sublayout.setColumnStretch(0, 1)
        sublayout.setColumnStretch(2, 3)
        sublayout.addWidget(self._lbl_available, 0, 0)
        sublayout.addWidget(self._lst_available, 1, 0)
        sublayout.addWidget(tlb_available, 2, 0)

        subsublayout = QVBoxLayout()
        subsublayout.addStretch()
        subsublayout.addWidget(self._btn_addtoqueue)
        subsublayout.addWidget(self._btn_addalltoqueue)
        subsublayout.addStretch()
        sublayout.addLayout(subsublayout, 1, 1)

        sublayout.addWidget(self._lbl_options, 0, 2)
        sublayout.addWidget(self._tbl_options, 1, 2)
        layout.addLayout(sublayout)

        sublayout = QHBoxLayout()
        sublayout.addStretch()
        sublayout.addWidget(self._btn_import)
        sublayout.addWidget(self._btn_start)
        sublayout.addWidget(self._btn_cancel)
        sublayout.addWidget(self._btn_close)
        layout.addLayout(sublayout)

        self.setLayout(layout)

        # Signal
        self._running_timer.timeout.connect(self._onRunningTimer)

        act_open.triggered.connect(self._onOpen)
        act_remove.triggered.connect(self._onRemove)
        act_clear.triggered.connect(self._onClear)

        self._btn_addtoqueue.released.connect(self._onAddToQueue)
        self._btn_addalltoqueue.released.connect(self._onAddAllToQueue)
        self._btn_start.released.connect(self._onStart)
        self._btn_cancel.released.connect(self._onCancel)
        self._btn_close.released.connect(self._onClose)
        self._btn_import.released.connect(self._onImport)

        self.options_added.connect(self._onOptionsAdded)
        self.options_running.connect(self._onOptionsRunning)
        self.options_simulated.connect(self._onOptionsSimulated)
        self.options_error.connect(self._onOptionsError)
        self.results_error.connect(self._onResultsError)

        # Defaults
        settings = get_settings()
        section = settings.add_section('gui')
        if hasattr(section, 'outputdir'):
            self._txt_outputdir.setPath(section.outputdir)
        if hasattr(section, 'maxworkers'):
            self._spn_workers.setValue(int(section.maxworkers))
        if hasattr(section, 'overwrite'):
            state = True if section.overwrite.lower() == 'true' else False
            self._chk_overwrite.setChecked(state)

    def _onDialogProgressProgress(self, progress, status):
        self._dlg_progress.setValue(progress * 100)
        self._dlg_progress.setLabelText(status)

    def _onDialogProgressCancel(self):
        self._dlg_progress.hide()
        if self._options_reader_thread is None:
            return
        self._options_reader_thread.cancel()
        self._options_reader_thread.quit()
        self._options_reader_thread.wait()

    def _onDialogProgressException(self, ex):
        self._dlg_progress.hide()
        self._options_reader_thread.quit()
        self._options_reader_thread.wait()
        messagebox.exception(self, ex)

    def _onRunningTimer(self):
        self._tbl_options.model().reset()

    def _onOpen(self):
        settings = get_settings()
        curdir = getattr(settings.gui, 'opendir', os.getcwd())

        filepath, namefilter = \
            QFileDialog.getOpenFileName(self, "Open", curdir,
                                        'Options [*.xml] (*.xml)')

        if not filepath or not namefilter:
            return
        settings.gui.opendir = os.path.dirname(filepath)

        if not filepath.endswith('.xml'):
            filepath += '.xml'

        self._options_reader_thread = _OptionsReaderWrapperThread(filepath)
        self._dlg_progress.canceled.connect(self._onDialogProgressCancel)
        self._options_reader_thread.resultReady.connect(self._onOpened)
        self._options_reader_thread.progressUpdated.connect(self._onDialogProgressProgress)
        self._options_reader_thread.exceptionRaised.connect(self._onDialogProgressException)
        self._options_reader_thread.start()

        self._dlg_progress.reset()
        self._dlg_progress.show()

    def _onOpened(self, options):
        self._dlg_progress.hide()
        self._options_reader_thread.quit()
        self._options_reader_thread.wait()
        self._options_reader_thread = None

        try:
            self._lst_available.model().addOptions(options)
        except Exception as ex:
            messagebox.exception(self, ex)

    def _onRemove(self):
        selection = self._lst_available.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Queue", "Select an options")
            return

        model = self._lst_available.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            model.popOptions(row)

    def _onClear(self):
        self._lst_available.model().clearOptions()

    def _onAddToQueue(self):
        selection = self._lst_available.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Queue", "Select an options")
            return

        model = self._lst_available.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            options = model.options(row)
            try:
                self._runner.put(options)
            except Exception as ex:
                messagebox.exception(self, ex)
                return

    def _onAddAllToQueue(self):
        model = self._lst_available.model()
        for row in reversed(range(0, model.rowCount())):
            options = model.options(row)
            try:
                self._runner.put(options)
            except Exception as ex:
                messagebox.exception(self, ex)
                return

    def _onStart(self):
        outputdir = self._txt_outputdir.path()
        if not outputdir:
            QMessageBox.critical(self, 'Start', 'Missing output directory')
            return
        max_workers = self._spn_workers.value()
        overwrite = self._chk_overwrite.isChecked()
        self.start(outputdir, overwrite, max_workers)

    def _onCancel(self):
        self.cancel()

    def _onClose(self):
        if self._runner is not None:
            self._runner.close()
        self._running_timer.stop()
        self.close()

    def _onImport(self):
        list_options = self._lst_available.model().listOptions()
        if not list_options:
            return

        # Select options
        dialog = _OptionsSelector(list_options)
        if not dialog.exec_():
            return
        options = dialog.options()

        # Start importer
        outputdir = self._runner.outputdir
        max_workers = self._runner.max_workers
        importer = LocalImporter(outputdir, max_workers)

        importer.start()
        importer.put(options)

        self._dlg_progress.show()
        try:
            while importer.is_alive():
                if self._dlg_progress.wasCanceled():
                    importer.cancel()
                    break
                self._dlg_progress.setValue(importer.progress * 100)
        finally:
            self._dlg_progress.hide()

    def _onOptionsAdded(self, options):
        logging.debug('runner: optionsAdded')
        self._tbl_options.model().addOptions(options)

    def _onOptionsRunning(self, options):
        logging.debug('runner: optionsRunning')
        self._tbl_options.model().resetOptions(options)

    def _onOptionsSimulated(self, options):
        logging.debug('runner: optionsSimulated')
        self._tbl_options.model().resetOptions(options)

    def _onOptionsError(self, options, ex):
        logging.debug('runner: optionsError')
        self._tbl_options.model().resetOptions(options)

    def _onResultsError(self, results, ex):
        logging.debug('runner: resultsError')
        self._tbl_options.model().reset()

    def closeEvent(self, event):
        if self.is_running():
            message = 'Runner is running. Do you want to continue?'
            answer = QMessageBox.question(self, 'Runner', message,
                                          QMessageBox.Yes | QMessageBox.No)
            if answer == QMessageBox.No:
                event.ignore()
                return

        self.cancel()
        self._dlg_progress.close()

        settings = get_settings()
        section = settings.add_section('gui')

        path = self._txt_outputdir.path()
        if path:
            section.outputdir = path
        section.maxworkers = str(self._spn_workers.value())
        section.overwrite = str(self._chk_overwrite.isChecked())

        settings.write()

        event.accept()

    def addAvailableOptions(self, options):
        self._lst_available.model().addOptions(options)

    def removeAvailableOptions(self, options):
        self._lst_available.model().removeOptions(options)

    def clearAvailableOptions(self):
        self._lbl_available.model().clearOptions()

    def start(self, outputdir, overwrite, max_workers):
        self._runner = LocalRunner(outputdir=outputdir,
                                   overwrite=overwrite,
                                   max_workers=max_workers)

        self._tbl_options.setModel(_StateOptionsTableModel(self._runner))

        self._spn_workers.setEnabled(False)
        self._txt_outputdir.setEnabled(False)
        self._chk_overwrite.setEnabled(False)
        self._btn_addtoqueue.setEnabled(True)
        self._btn_addalltoqueue.setEnabled(True)
        self._btn_start.setEnabled(False)
        self._btn_cancel.setEnabled(True)
        self._btn_close.setEnabled(False)
        self._btn_import.setEnabled(True)

        self._runner.options_added.connect(self.options_added.emit)
        self._runner.options_running.connect(self.options_running.emit)
        self._runner.options_simulated.connect(self.options_simulated.emit)
        self._runner.options_error.connect(self.options_error.emit)
        self._runner.results_saved.connect(self.results_saved.emit)
        self._runner.results_error.connect(self.results_error.emit)

        self._running_timer.start()
        self._runner.start()

    def cancel(self):
        if self._runner is None:
            return
        self._runner.cancel()
        self._running_timer.stop()

        self._runner.options_added.disconnect(self.options_added.emit)
        self._runner.options_running.disconnect(self.options_running.emit)
        self._runner.options_simulated.disconnect(self.options_simulated.emit)
        self._runner.options_error.disconnect(self.options_error.emit)
        self._runner.results_saved.disconnect(self.results_saved.emit)
        self._runner.results_error.disconnect(self.results_error.emit)

        self._runner = None

        self._spn_workers.setEnabled(True)
        self._txt_outputdir.setEnabled(True)
        self._chk_overwrite.setEnabled(True)
        self._btn_addtoqueue.setEnabled(False)
        self._btn_addalltoqueue.setEnabled(False)
        self._btn_start.setEnabled(True)
        self._btn_cancel.setEnabled(False)
        self._btn_close.setEnabled(True)
        self._btn_import.setEnabled(False)

    def is_running(self):
        return self._runner is not None and self._runner.is_alive()
예제 #37
0
class LayerListWidget(_ParameterWidget):

    def __init__(self, parameter, parent=None):
        _ParameterWidget.__init__(self, parameter, parent)

        # Variables
        model = _LayerModel()
        self._material_class = Material

        # Actions
        act_add = QAction(getIcon("list-add"), "Add layer", self)
        act_remove = QAction(getIcon("list-remove"), "Remove layer", self)
        act_clean = QAction(getIcon('edit-clear'), "Clear", self)

        # Widgets
        self._cb_unit = UnitComboBox('m')
        self._cb_unit.setUnit('um')

        self._tbl_layers = QTableView()
        self._tbl_layers.setModel(model)
        self._tbl_layers.setItemDelegate(_LayerDelegate())
        header = self._tbl_layers.horizontalHeader()
        header.setResizeMode(QHeaderView.Stretch)
        header.setStyleSheet('color: blue')

        self._tlb_layers = QToolBar()
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._tlb_layers.addWidget(spacer)
        self._tlb_layers.addAction(act_add)
        self._tlb_layers.addAction(act_remove)
        self._tlb_layers.addAction(act_clean)

        # Layouts
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        sublayout = QHBoxLayout()
        sublayout.addStretch()
        sublayout.addWidget(QLabel('Thickness unit'))
        sublayout.addWidget(self._cb_unit)
        layout.addLayout(sublayout)

        layout.addWidget(self._tbl_layers)
        layout.addWidget(self._tlb_layers)
        self.setLayout(layout)

        # Signals
        self.valuesChanged.connect(self._onChanged)
        self.validationRequested.connect(self._onChanged)

        act_add.triggered.connect(self._onAdd)
        act_remove.triggered.connect(self._onRemove)
        act_clean.triggered.connect(self._onClear)

        self._tbl_layers.doubleClicked.connect(self._onDoubleClicked)

        model.dataChanged.connect(self.valuesChanged)
        model.rowsInserted.connect(self.valuesChanged)
        model.rowsRemoved.connect(self.valuesChanged)

        self.validationRequested.emit()

    def _onChanged(self):
        if self.hasAcceptableInput():
            self._tbl_layers.setStyleSheet("background: none")
        else:
            self._tbl_layers.setStyleSheet("background: pink")

    def _onDoubleClicked(self, index):
        if index.column() != 0:
            return

        model = self._tbl_layers.model()
        materials = model.materials(index)

        if len(materials) == 0:
            dialog = get_material_dialog_class(self._material_class)()
        elif len(materials) == 1:
            dialog = get_material_dialog_class(self._material_class)()
            dialog.setValue(materials[0])
        else:
            dialog = MaterialListDialog()
            dialog.setMaterialClass(self._material_class)
            dialog.setValues(materials)

        dialog.setReadOnly(self.isReadOnly())

        if not dialog.exec_():
            return

        model.setData(index, dialog.values())

    def _onAdd(self):
        index = self._tbl_layers.selectionModel().currentIndex()
        model = self._tbl_layers.model()
        model.insertRows(index.row() + 1)

        # Show material dialog right away
        index = model.createIndex(index.row() + 1, 0)
        self._onDoubleClicked(index)

    def _onRemove(self):
        selection = self._tbl_layers.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Layer", "Select a row")
            return

        model = self._tbl_layers.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            model.removeRow(row)

    def _onClear(self):
        model = self._tbl_layers.model()
        for row in reversed(range(model.rowCount())):
            model.removeRow(row)

    def values(self):
        factor = self._cb_unit.factor()

        layers = []
        for material, thickness in self._tbl_layers.model().layers():
            if not material or not thickness:
                continue
            thickness_m = np.array(thickness, ndmin=1) * factor
            layers.append(_MockLayer(material, thickness_m))

        return layers

    def setValues(self, layers):
        layers = np.array(layers, ndmin=1)
        factor = self._cb_unit.factor()

        model = self._tbl_layers.model()
        model.removeRows(0, model.rowCount())
        model.insertRows(0, len(layers))

        for i, layer in enumerate(layers):
            model.setData(model.index(i, 0), layer.material)
            model.setData(model.index(i, 1), layer.thickness_m / factor)

    def isReadOnly(self):
        return not self._cb_unit.isEnabled() and \
            not self._tlb_layers.isVisible()

    def setReadOnly(self, state):
        self._cb_unit.setEnabled(not state)
        self._tlb_layers.setVisible(not state)

        style = 'color: none' if state else 'color: blue'
        self._tbl_layers.horizontalHeader().setStyleSheet(style)
        self._tbl_layers.itemDelegate().setReadOnly(state)

    def setMaterialClass(self, clasz):
        self._material_class = clasz
예제 #38
0
class DetectorWizardPage(_ExpandableOptionsWizardPage):

    class _DetectorComboBoxModel(QAbstractListModel):

        def __init__(self):
            QAbstractListModel.__init__(self)
            self._detectors = []

        def rowCount(self, *args, **kwargs):
            return len(self._detectors)

        def data(self, index, role=Qt.DisplayRole):
            if not index.isValid() or \
                    not (0 <= index.row() < self.rowCount()):
                return None

            if role == Qt.TextAlignmentRole:
                return Qt.AlignCenter

            if role != Qt.DisplayRole:
                return None

            return self._detectors[index.row()]['text']

        def setData(self, index, value, role=Qt.EditRole):
            if not index.isValid() or \
                    not (0 <= index.row() < len(self._detectors)):
                return False

            row = index.row()
            self._detectors[row] = value

            self.dataChanged.emit(index, index)
            return True

        def insertRows(self, row, count=1, parent=None):
            if count == 0:
                return False
            if parent is None:
                parent = QModelIndex()
            self.beginInsertRows(QModelIndex(), row, row + count - 1)

            for _ in range(count):
                value = {'text': '', 'class': None, 'widget_class': None}
                self._detectors.insert(row, value)

            self.endInsertRows()
            return True

        def removeRows(self, row, count=1, parent=None):
            if count == 0:
                return False
            if parent is None:
                parent = QModelIndex()
            self.beginRemoveRows(QModelIndex(), row, row + count - 1)

            for index in reversed(range(row, row + count)):
                self._detectors.pop(index)

            self.endRemoveRows()
            return True

        def append(self, text, clasz, widget_class):
            self.insert(self.rowCount(), text, clasz, widget_class)

        def insert(self, row, text, clasz, widget_class):
            self.insertRows(row)
            value = {'text': text, 'class': clasz, 'widget_class': widget_class}
            self.setData(self.createIndex(row, 0), value)

        def clear(self):
            self.removeRows(0, self.rowCount())

        def widget_class(self, index):
            return self._detectors[index]['widget_class']

    class _DetectorTableModel(QAbstractTableModel):

        def __init__(self):
            QAbstractTableModel.__init__(self)
            self._detectors = []

        def rowCount(self, *args, **kwargs):
            return len(self._detectors)

        def columnCount(self, *args, **kwargs):
            return 2

        def data(self, index, role=Qt.DisplayRole):
            if not index.isValid() or \
                    not (0 <= index.row() < len(self._detectors)):
                return None

            if role == Qt.TextAlignmentRole:
                return Qt.AlignCenter

            if role == Qt.DisplayRole or role == Qt.ToolTipRole:
                key, detector = self._detectors[index.row()]
                column = index.column()
                if column == 0:
                    return key
                elif column == 1:
                    return str(detector) if detector is not None else ''

            return None

        def headerData(self, section , orientation, role):
            if role != Qt.DisplayRole:
                return None
            if orientation == Qt.Horizontal:
                if section == 0:
                    return 'Key'
                elif section == 1:
                    return 'Detector'
            elif orientation == Qt.Vertical:
                return str(section + 1)

        def flags(self, index):
            if not index.isValid():
                return Qt.ItemIsEnabled

            return Qt.ItemFlags(QAbstractTableModel.flags(self, index) |
                                Qt.ItemIsEditable)

        def setData(self, index, value, role=Qt.EditRole):
            if not index.isValid() or \
                    not (0 <= index.row() < len(self._detectors)):
                return False

            row = index.row()
            column = index.column()
            self._detectors[row][column] = value

            self.dataChanged.emit(index, index)
            return True

        def insertRows(self, row, count=1, parent=None):
            if count == 0:
                return False
            if parent is None:
                parent = QModelIndex()
            self.beginInsertRows(parent, row, row + count - 1)

            for _ in range(count):
                self._detectors.insert(row, ['untitled', None])

            self.endInsertRows()
            return True

        def removeRows(self, row, count=1, parent=None):
            if count == 0:
                return False
            if parent is None:
                parent = QModelIndex()
            self.beginRemoveRows(parent, row, row + count - 1)

            for index in reversed(range(row, row + count)):
                self._detectors.pop(index)

            self.endRemoveRows()
            return True

        def append(self, key, detector):
            self.insert(self.rowCount(), key, detector)

        def insert(self, index, key, detector):
            self.insertRows(index)
            self.setData(self.createIndex(index, 0), key)
            self.setData(self.createIndex(index, 1), detector)

        def modify(self, index, key, detector):
            self.setData(self.createIndex(index, 0), key)
            self.setData(self.createIndex(index, 1), detector)

        def clear(self):
            self.removeRows(0, self.rowCount())

        def detectors(self):
            detectors = {}
            for key, detector in self._detectors:
                if detector is not None:
                    detectors.setdefault(key, []).append(detector)
            return detectors

        def detector(self, index):
            return self._detectors[index.row()][1]

        def key(self, index):
            return self._detectors[index.row()][0]

    class _DetectorTableDelegate(QItemDelegate):

        def __init__(self, parent=None):
            QItemDelegate.__init__(self, parent)

        def createEditor(self, parent, option, index):
            column = index.column()
            if column == 0:
                editor = QLineEdit(parent)
                editor.setValidator(QRegExpValidator(QRegExp(r"^(?!\s*$).+")))
                return editor
            elif column == 1:
                return None

        def setEditorData(self, editor, index):
            column = index.column()
            if column == 0:
                key = index.model().data(index, Qt.DisplayRole)
                editor.setText(key)

        def setModelData(self, editor, model, index):
            column = index.column()
            if column == 0:
                if not editor.hasAcceptableInput():
                    return
                model.setData(index, editor.text())

    def __init__(self, options, parent=None):
        _ExpandableOptionsWizardPage.__init__(self, options, parent)
        self.setTitle('Detector')

    def _initUI(self):
        # Variables
        self._widgets = {}
        tbl_model = self._DetectorTableModel()

        # Widgets
        self._cb_detector = QComboBox()
        self._cb_detector.setModel(self._DetectorComboBoxModel())

        btn_detector_add = QPushButton()
        btn_detector_add.setIcon(getIcon("list-add"))

        self._tbl_detector = QTableView()
        self._tbl_detector.setModel(tbl_model)
        self._tbl_detector.setItemDelegate(self._DetectorTableDelegate())
        header = self._tbl_detector.horizontalHeader()
        header.setResizeMode(1, QHeaderView.Stretch)
        policy = self._tbl_detector.sizePolicy()
        policy.setVerticalStretch(True)
        self._tbl_detector.setSizePolicy(policy)

        tlb_detector = QToolBar()
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        tlb_detector.addWidget(spacer)
        act_remove = tlb_detector.addAction(getIcon("list-remove"), "Remove detector")
        act_clear = tlb_detector.addAction(getIcon("edit-clear"), "Clear")

        # Layouts
        layout = _ExpandableOptionsWizardPage._initUI(self)

        sublayout = QHBoxLayout()
        sublayout.addWidget(self._cb_detector, 1)
        sublayout.addWidget(btn_detector_add)
        layout.addRow("Select", sublayout)

        layout.addRow(self._tbl_detector)
        layout.addRow(tlb_detector)

        # Signals
        btn_detector_add.released.connect(self._onDetectorAdd)
        act_remove.triggered.connect(self._onDetectorRemove)
        act_clear.triggered.connect(self._onDetectorClear)

        self._tbl_detector.doubleClicked.connect(self._onDetectorDoubleClicked)

        tbl_model.dataChanged.connect(self.valueChanged)
        tbl_model.rowsInserted.connect(self.valueChanged)
        tbl_model.rowsRemoved.connect(self.valueChanged)

        return layout

    def _onDetectorAdd(self):
        index = self._tbl_detector.selectionModel().currentIndex()
        tbl_model = self._tbl_detector.model()
        cb_model = self._cb_detector.model()

        widget_class = cb_model.widget_class(self._cb_detector.currentIndex())
        wdg_detector = widget_class()

        dialog = _DetectorDialog(wdg_detector)
        if not dialog.exec_():
            return

        tbl_model.insert(index.row() + 1, dialog.key(), dialog.detector())

    def _onDetectorRemove(self):
        selection = self._tbl_detector.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Detector", "Select a row")
            return

        tbl_model = self._tbl_detector.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            tbl_model.removeRow(row)

    def _onDetectorClear(self):
        model = self._tbl_detector.model()
        for row in reversed(range(model.rowCount())):
            model.removeRow(row)

    def _onDetectorDoubleClicked(self, index):
        if index.column() != 1:
            return

        tbl_model = self._tbl_detector.model()
        key = tbl_model.key(index)
        detector = tbl_model.detector(index)
        widget_class = self._widgets[detector.__class__]
        wdg_detector = widget_class()
        wdg_detector.setValue(detector)

        dialog = _DetectorDialog(wdg_detector, key)
        if not dialog.exec_():
            return

        tbl_model.modify(index.row(), dialog.key(), dialog.detector())

    def initializePage(self):
        _ExpandableOptionsWizardPage.initializePage(self)

        tbl_model = self._tbl_detector.model()
        cb_model = self._cb_detector.model()

        # Clear
        self._widgets.clear()
        tbl_model.clear()
        cb_model.clear()

        # Populate combo box
        it = self._iter_widgets('pymontecarlo.ui.gui.options.detector',
                                'DETECTORS')
        for clasz, widget_class, programs in it:
            widget = widget_class()
            self._widgets[clasz] = widget_class

            program_text = ', '.join(map(attrgetter('name'), programs))
            text = '{0} ({1})'.format(widget.accessibleName(), program_text)

            cb_model.append(text, clasz, widget_class)

            del widget

        self._cb_detector.setCurrentIndex(0)

        # Add detector(s)
        for key, detectors in self.options().detectors.items():
            detectors = np.array(detectors, ndmin=1)
            for detector in detectors:
                if not detector.__class__ in self._widgets:
                    continue
                tbl_model.append(key, detector)

    def validatePage(self):
        tbl_model = self._tbl_detector.model()
        if tbl_model.rowCount() == 0:
            return False

        self.options().detectors.clear()
        self.options().detectors.update(tbl_model.detectors())

        return True

    def expandCount(self):
        if self._tbl_detector.model().rowCount() == 0:
            return 0

        try:
            count = 1

            for detectors in self._tbl_detector.model().detectors().values():
                count *= len(detectors)
                for detector in detectors:
                    count *= len(expand(detector))

            return count
        except:
            return 0
예제 #39
0
파일: gui05.py 프로젝트: yysynergy/pparser
class MainWindow(QMainWindow):
    def __init__(self, datta):
        QMainWindow.__init__(self)
        self.setWindowTitle('Project Parser')
        appIcon = QIcon('search.png')
        self.setWindowIcon(appIcon)
        self.viewPortBL = QDesktopWidget().availableGeometry().topLeft()
        self.viewPortTR = QDesktopWidget().availableGeometry().bottomRight()
        self.margin = int(QDesktopWidget().availableGeometry().width()*0.1/2)
        self.shirina = QDesktopWidget().availableGeometry().width() - self.margin*2
        self.visota = QDesktopWidget().availableGeometry().height() - self.margin*2
        self.setGeometry(self.viewPortBL.x() + self.margin, self.viewPortBL.y() + self.margin,
                         self.shirina, self.visota)
        # statusbar
        self.myStatusBar = QStatusBar()
        self.setStatusBar(self.myStatusBar)
        
        #lower long layout
        self.lowerLong = QFrame()
        self.detailsLabel = QLabel()
        self.skillsLabel = QLabel()
        self.urlLabel = QLabel()
        self.locationLabel = QLabel()
        self.skillsLabel.setText('skills')
        self.detailsLabel.setWordWrap(True)
        self.la = QVBoxLayout()
        self.la.addWidget(self.detailsLabel)
        self.la.addWidget(self.skillsLabel)
        self.la.addWidget(self.urlLabel)
        self.la.addWidget(self.locationLabel)
        self.lowerLong.setLayout(self.la)

        # table
        self.source_model = MyTableModel(self, datta, ['Id', 'Date', 'Title'])
        self.proxy_model = myTableProxy(self)
        self.proxy_model.setSourceModel(self.source_model)
        self.proxy_model.setDynamicSortFilter(True)
        self.table_view = QTableView()
        self.table_view.setModel(self.proxy_model)
        self.table_view.setAlternatingRowColors(True)
        self.table_view.resizeColumnsToContents()
        self.table_view.resizeRowsToContents()
        self.table_view.horizontalHeader().setStretchLastSection(True)
        self.table_view.setSortingEnabled(True)
        self.table_view.sortByColumn(2, Qt.AscendingOrder)

        # events
        self.selection = self.table_view.selectionModel()
        self.selection.selectionChanged.connect(self.handleSelectionChanged)
        #DO NOT use CreateIndex() method, use index()
        index = self.proxy_model.index(0,0)
        self.selection.select(index, QItemSelectionModel.Select)
        
        self.upperLong = self.table_view  

        # right side widgets
        self.right = QFrame()
        self.la1 = QVBoxLayout()
        self.btnDownload = QPushButton('Download data')
        self.btnDownload.clicked.connect(self.download)
        self.myButton = QPushButton('Show Skillls')
        self.myButton.clicked.connect(self.showAllSkills)
        self.btnSearchByWord = QPushButton('Search by word(s)')
        self.btnSearchByWord.clicked.connect(self.onSearchByWord)
        self.btnResetFilter= QPushButton('Discard Filter')
        self.btnResetFilter.clicked.connect(self.discardFilter)
        self.btnCopyURL = QPushButton('URL to Clipboard')
        self.btnCopyURL.clicked.connect(self.copyToClipboard)
        self.btnExit = QPushButton('Exit')
        self.btnExit.clicked.connect(lambda: sys.exit())
        self.dateTimeStamp = QLabel()
        self.la1.addWidget(self.btnDownload)
        self.la1.addSpacing(10)
        self.la1.addWidget(self.myButton)
        self.la1.addSpacing(10)
        self.la1.addWidget(self.btnSearchByWord)
        self.la1.addSpacing(10)
        self.la1.addWidget(self.btnResetFilter)
        self.la1.addSpacing(10)
        self.la1.addWidget(self.btnCopyURL)
        self.la1.addSpacing(70)
        self.la1.addWidget(self.btnExit)
        self.la1.addStretch(stretch=0)
        self.la1.addWidget(self.dateTimeStamp)
        self.right.setLayout(self.la1)
        self.right.setFrameShape(QFrame.StyledPanel)

        # splitters
        self.horiSplit = QSplitter(Qt.Vertical)
        self.horiSplit.addWidget(self.upperLong)
        self.horiSplit.addWidget(self.lowerLong)
        self.horiSplit.setSizes([self.visota/2, self.visota/2])
        self.vertiSplit = QSplitter(Qt.Horizontal)
        self.vertiSplit.addWidget(self.horiSplit)
        self.vertiSplit.addWidget(self.right)
        self.vertiSplit.setSizes([self.shirina*3/4, self.shirina*1/4])
        self.setCentralWidget(self.vertiSplit)
        
        self.settings = QSettings('elance.ini', QSettings.IniFormat)
        self.settings.beginGroup('DATE_STAMP')
        self.dateTimeStamp.setText('Data actuality: %s' % self.settings.value('date/time'))
        self.settings.endGroup()
        self.statusText = ''

    def handleSelectionChanged(self, selected, deselected):
        for index in selected.first().indexes():
            #print('Row %d is selected' % index.row())
            ind = index.model().mapToSource(index)
            desc = ind.model().mylist[ind.row()]['Description']
            self.detailsLabel.setText(desc)
            skills = ', '.join(ind.model().mylist[ind.row()]['Skills']).strip()
            self.skillsLabel.setText(skills)
            url = ind.model().mylist[ind.row()]['URL']
            self.urlLabel.setText(url)
            location = ind.model().mylist[ind.row()]['Location']
            self.locationLabel.setText(location)
    
    def showAllSkills(self):
        listSkills = []
        for elem in self.source_model.mylist:
            listSkills += elem['Skills']
        allSkills = Counter(listSkills)
        tbl = MyTableModel(self, allSkills.items(), ['Skill', 'Freq'])
        win = skillsWindow(tbl, self.table_view)
        win.exec_()
    
    def discardFilter(self):
        self.table_view.model().emit(SIGNAL("modelAboutToBeReset()"))
        self.table_view.model().criteria = {}
        self.table_view.model().emit(SIGNAL("modelReset()"))
        self.table_view.resizeRowsToContents()
        
    def download(self):
        self.btnDownload.setDisabled(True)
        self.statusLabel = QLabel('Connecting')
        self.progressBar = QProgressBar()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(100)
        self.myStatusBar.addWidget(self.statusLabel, 2)
        self.myStatusBar.addWidget(self.progressBar, 1)
        self.progressBar.setValue(1)
        self.settings.beginGroup('URLS')
        initialLink = self.settings.value('CategoriesDetailed/VahaSelected/InitialLink')
        pagingLink = self.settings.value('CategoriesDetailed/VahaSelected/PagingLink')
        self.settings.endGroup()
        downloader = Downloader(initialLink, pagingLink, 25, 5)
        downloader.messenger.downloadProgressChanged.connect(self.onDownloadProgressChanged)
        downloader.messenger.downloadComplete.connect(self.onDownloadComplete)
        downloader.download()
    
    def onDownloadComplete(self):
        #QMessageBox.information(self, 'Download complete', 'Download complete!', QMessageBox.Ok)
        self.table_view.model().emit(SIGNAL("modelAboutToBeReset()"))
        self.settings.beginGroup('DATE_STAMP')
        self.settings.setValue('date/time', time.strftime('%d-%b-%Y, %H:%M:%S'))
        self.dateTimeStamp.setText('Data actuality: %s' % self.settings.value('date/time'))
        self.settings.endGroup()
        with open("elance.json") as json_file:
            jobDB = json.load(json_file)
        for elem in jobDB:
            words = nltk.tokenize.regexp_tokenize(elem['Title'].lower(), r'\w+')
            elem['Tokens'] = words
            elem['Skills'] = [t.strip() for t in elem['Skills'].split(',')]
        self.source_model.mylist = jobDB
        self.table_view.model().emit(SIGNAL("modelReset()"))
        self.btnDownload.setEnabled(True)
        self.myStatusBar.removeWidget(self.statusLabel)
        self.myStatusBar.removeWidget(self.progressBar)
        self.myStatusBar.showMessage(self.statusText, timeout = 5000)
                
    
    def onDownloadProgressChanged(self, stata):
        self.progressBar.setValue(stata[2])
        #text = 'Processed records{:5d} of{:5d}'.format(percentage[0], percentage[1])
        bajtikov = '{:,}'.format(stata[5])
        self.statusText = 'Processed page{:4d} of{:4d}. \
               Job entries{:5d} of{:5d}. \
               Downloaded{:>12s} Bytes'.format(stata[3], stata[4],
                                              stata[0], stata[1],
                                              bajtikov)
        self.statusLabel.setText(self.statusText)
        
    def copyToClipboard(self):
        clipboard = QApplication.clipboard()
        clipboard.setText(self.urlLabel.text())
        self.myStatusBar.showMessage(self.urlLabel.text(), timeout = 3000)
    
    def onSearchByWord(self):
        text, ok = QInputDialog.getText(self, 'Search the base by word(s)', 'Enter your keyword/phrase to search for:')
        if ok:
            words = [t.strip() for t in nltk.tokenize.regexp_tokenize(text.lower(), r'\w+')]
            self.table_view.model().emit(SIGNAL("modelAboutToBeReset()"))
            self.table_view.model().criteria = {'Description' : words}
            self.table_view.model().emit(SIGNAL("modelReset()"))
예제 #40
0
class PenelopeMaterialDialog(_MaterialDialog):

    def __init__(self, parent=None):
        _MaterialDialog.__init__(self, parent)
        self.setWindowTitle('Material')
        self.setMinimumWidth(1000)

    def _initUI(self):
        # Variables
        model_forcing = _InteractionForcingTableModel()

        # Actions
        act_add_forcing = QAction(getIcon("list-add"), "Add interaction forcing", self)
        act_remove_forcing = QAction(getIcon("list-remove"), "Remove interaction forcing", self)

        # Widgets
        self._lbl_elastic_scattering_c1 = QLabel('C1')
        self._lbl_elastic_scattering_c1.setStyleSheet("color: blue")
        self._txt_elastic_scattering_c1 = MultiNumericalLineEdit()
        self._txt_elastic_scattering_c1.setValidator(_ElasticScatteringValidator())
        self._txt_elastic_scattering_c1.setValues([0.0])

        self._lbl_elastic_scattering_c2 = QLabel('C2')
        self._lbl_elastic_scattering_c2.setStyleSheet("color: blue")
        self._txt_elastic_scattering_c2 = MultiNumericalLineEdit()
        self._txt_elastic_scattering_c2.setValidator(_ElasticScatteringValidator())
        self._txt_elastic_scattering_c2.setValues([0.0])

        self._lbl_cutoff_energy_inelastic = QLabel('Inelastic collisions')
        self._lbl_cutoff_energy_inelastic.setStyleSheet("color: blue")
        self._txt_cutoff_energy_inelastic = MultiNumericalLineEdit()
        self._txt_cutoff_energy_inelastic.setValidator(_CutoffEnergyValidator())
        self._txt_cutoff_energy_inelastic.setValues([50.0])
        self._cb_cutoff_energy_inelastic = UnitComboBox('eV')

        self._lbl_cutoff_energy_bremsstrahlung = QLabel('Bremsstrahlung emission')
        self._lbl_cutoff_energy_bremsstrahlung.setStyleSheet("color: blue")
        self._txt_cutoff_energy_bremsstrahlung = MultiNumericalLineEdit()
        self._txt_cutoff_energy_bremsstrahlung.setValidator(_CutoffEnergyValidator())
        self._txt_cutoff_energy_bremsstrahlung.setValues([50.0])
        self._cb_cutoff_energy_bremsstrahlung = UnitComboBox('eV')

        self._lbl_maximum_step_length = QLabel('Maximum step length')
        self._lbl_maximum_step_length.setStyleSheet("color: blue")
        self._txt_maximum_step_length = MultiNumericalLineEdit()
        self._txt_maximum_step_length.setValidator(_MaximumStepLengthValidator())
        self._txt_maximum_step_length.setValues([1e15])
        self._cb_maximum_step_length_unit = UnitComboBox('m')

        self._tbl_forcing = QTableView()
        self._tbl_forcing.setModel(model_forcing)
        self._tbl_forcing.setItemDelegate(_InteractionForcingDelegate())
        header = self._tbl_forcing.horizontalHeader()
        header.setResizeMode(QHeaderView.Stretch)

        self._tlb_forcing = QToolBar()
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._tlb_forcing.addWidget(spacer)
        self._tlb_forcing.addAction(act_add_forcing)
        self._tlb_forcing.addAction(act_remove_forcing)

        # Layouts
        layout = QHBoxLayout()

        layout.addLayout(_MaterialDialog._initUI(self), 1)

        frame = QFrame()
        frame.setFrameShape(QFrame.VLine)
        frame.setFrameShadow(QFrame.Sunken)
        layout.addWidget(frame)

        sublayout = QVBoxLayout()

        box_elastic_scattering = QGroupBox("Elastic scattering")
        boxlayout = QFormLayout()
        boxlayout.addRow(self._lbl_elastic_scattering_c1, self._txt_elastic_scattering_c1)
        boxlayout.addRow(self._lbl_elastic_scattering_c2, self._txt_elastic_scattering_c2)
        box_elastic_scattering.setLayout(boxlayout)
        sublayout.addWidget(box_elastic_scattering)

        box_cutoff_energy = QGroupBox("Cutoff energy")
        boxlayout = QFormLayout()
        boxsublayout = QHBoxLayout()
        boxsublayout.addWidget(self._txt_cutoff_energy_inelastic, 1)
        boxsublayout.addWidget(self._cb_cutoff_energy_inelastic)
        boxlayout.addRow(self._lbl_cutoff_energy_inelastic, boxsublayout)
        boxsublayout = QHBoxLayout()
        boxsublayout.addWidget(self._txt_cutoff_energy_bremsstrahlung, 1)
        boxsublayout.addWidget(self._cb_cutoff_energy_bremsstrahlung)
        boxlayout.addRow(self._lbl_cutoff_energy_bremsstrahlung, boxsublayout)
        box_cutoff_energy.setLayout(boxlayout)
        sublayout.addWidget(box_cutoff_energy)

        subsublayout = QFormLayout()
        subsubsublayout = QHBoxLayout()
        subsubsublayout.addWidget(self._txt_maximum_step_length, 1)
        subsubsublayout.addWidget(self._cb_maximum_step_length_unit)
        subsublayout.addRow(self._lbl_maximum_step_length, subsubsublayout)
        sublayout.addLayout(subsublayout)

        box_forcing = QGroupBox('Interaction forcing')
        boxlayout = QVBoxLayout()
        boxlayout.addWidget(self._tbl_forcing)
        boxlayout.addWidget(self._tlb_forcing)
        box_forcing.setLayout(boxlayout)
        sublayout.addWidget(box_forcing)

        sublayout.addStretch()

        layout.addLayout(sublayout, 1)

        # Signals
        self._txt_elastic_scattering_c1.textChanged.connect(self._onElasticScatteringC1Changed)
        self._txt_elastic_scattering_c2.textChanged.connect(self._onElasticScatteringC2Changed)
        self._txt_cutoff_energy_inelastic.textChanged.connect(self._onCutoffEnergyInelasticChanged)
        self._txt_cutoff_energy_bremsstrahlung.textChanged.connect(self._onCutoffEnergyBremsstrahlungChanged)
        self._txt_maximum_step_length.textChanged.connect(self._onMaximumStepLengthChanged)

        act_add_forcing.triggered.connect(self._onForcingAdd)
        act_remove_forcing.triggered.connect(self._onForcingRemove)

        return layout

    def _onElasticScatteringC1Changed(self):
        if self._txt_elastic_scattering_c1.hasAcceptableInput():
            self._txt_elastic_scattering_c1.setStyleSheet('background: none')
        else:
            self._txt_elastic_scattering_c1.setStyleSheet('background: pink')

    def _onElasticScatteringC2Changed(self):
        if self._txt_elastic_scattering_c2.hasAcceptableInput():
            self._txt_elastic_scattering_c2.setStyleSheet('background: none')
        else:
            self._txt_elastic_scattering_c2.setStyleSheet('background: pink')

    def _onCutoffEnergyInelasticChanged(self):
        if self._txt_cutoff_energy_inelastic.hasAcceptableInput():
            self._txt_cutoff_energy_inelastic.setStyleSheet('background: none')
        else:
            self._txt_cutoff_energy_inelastic.setStyleSheet('background: pink')

    def _onCutoffEnergyBremsstrahlungChanged(self):
        if self._txt_cutoff_energy_bremsstrahlung.hasAcceptableInput():
            self._txt_cutoff_energy_bremsstrahlung.setStyleSheet('background: none')
        else:
            self._txt_cutoff_energy_bremsstrahlung.setStyleSheet('background: pink')

    def _onMaximumStepLengthChanged(self):
        if self._txt_maximum_step_length.hasAcceptableInput():
            self._txt_maximum_step_length.setStyleSheet('background: none')
        else:
            self._txt_maximum_step_length.setStyleSheet('background: pink')

    def _onForcingAdd(self):
        index = self._tbl_forcing.selectionModel().currentIndex()
        model = self._tbl_forcing.model()
        model.insertRows(index.row() + 1)

    def _onForcingRemove(self):
        selection = self._tbl_forcing.selectionModel().selection().indexes()
        if len(selection) == 0:
            QMessageBox.warning(self, "Interaction forcing", "Select a row")
            return

        model = self._tbl_forcing.model()
        for row in sorted(map(methodcaller('row'), selection), reverse=True):
            model.removeRow(row)

    def _getParametersDict(self):
        params = _MaterialDialog._getParametersDict(self)

        params['c1'] = self._txt_elastic_scattering_c1.values().tolist()
        params['c2'] = self._txt_elastic_scattering_c2.values().tolist()

        wcc = self._txt_cutoff_energy_inelastic.values() * self._cb_cutoff_energy_inelastic.factor()
        params['wcc'] = wcc.tolist()

        wcr = self._txt_cutoff_energy_bremsstrahlung.values() * self._cb_cutoff_energy_bremsstrahlung.factor()
        params['wcr'] = wcr.tolist()

        dsmax = self._txt_maximum_step_length.values() * self._cb_maximum_step_length_unit.factor()
        params['dsmax'] = dsmax.tolist()

        params['forcings'] = \
            self._tbl_forcing.model().interaction_forcings()

        return params

    def _generateName(self, parameters, varied):
        name = parameters.pop('name')
        if name is None:
            name = PenelopeMaterial.generate_name(parameters['composition'])

        parts = [name]
        for key in varied:
            if key == 'composition':
                continue
            elif key == 'forcings':
                forcing = parameters[key][0]
                forcer = forcing.forcer
                wlow = forcing.weight[0]
                whigh = forcing.weight[1]
                parts.append('forcings={0:n}_{1:n}_{2:n}'.format(forcer, wlow, whigh))
            else:
                parts.append('{0:s}={1:n}'.format(key, parameters[key]))
        return '+'.join(parts)

    def _createMaterial(self, parameters, varied):
        mat = _MaterialDialog._createMaterial(self, parameters, varied)

        c1 = parameters['c1']
        c2 = parameters['c2']
        wcc = parameters['wcc']
        wcr = parameters['wcr']
        dsmax = parameters['dsmax']
        forcings = parameters['forcings']

        return PenelopeMaterial(mat.composition, mat.name, mat.density_kg_m3,
                                mat.absorption_energy_eV,
                                elastic_scattering=(c1, c2),
                                cutoff_energy_inelastic_eV=wcc,
                                cutoff_energy_bremsstrahlung_eV=wcr,
                                interaction_forcings=forcings,
                                maximum_step_length_m=dsmax)

    def setValue(self, material):
        _MaterialDialog.setValue(self, material)

        # Elastic scattering
        c1, c2 = material.elastic_scattering
        self._txt_elastic_scattering_c1.setValues(c1)
        self._txt_elastic_scattering_c2.setValues(c2)

        # Cutoff energy
        self._txt_cutoff_energy_inelastic.setValues(material.cutoff_energy_inelastic_eV)
        self._cb_cutoff_energy_inelastic.setUnit('eV')

        self._txt_cutoff_energy_bremsstrahlung.setValues(material.cutoff_energy_bremsstrahlung_eV)
        self._cb_cutoff_energy_bremsstrahlung.setUnit('eV')

        # Maximum step length
        self._txt_maximum_step_length.setValues(material.maximum_step_length_m)
        self._cb_maximum_step_length_unit.setUnit('m')

        # Interaction forcings
        forcings = material.interaction_forcings

        model = self._tbl_forcing.model()
        model.removeRows(0, model.rowCount())
        model.insertRows(1, len(forcings))

        for row, forcing in enumerate(forcings):
            model.setData(model.index(row, 0), forcing.particle)
            model.setData(model.index(row, 1), forcing.collision)
            model.setData(model.index(row, 2), forcing.forcer)
            model.setData(model.index(row, 3), forcing.weight[0])
            model.setData(model.index(row, 4), forcing.weight[1])

    def setReadOnly(self, state):
        _MaterialDialog.setReadOnly(self, state)

        style = 'color: none' if state else 'color: blue'
        self._lbl_elastic_scattering_c1.setStyleSheet(style)
        self._txt_elastic_scattering_c1.setReadOnly(state)

        self._lbl_elastic_scattering_c2.setStyleSheet(style)
        self._txt_elastic_scattering_c2.setReadOnly(state)

        self._lbl_cutoff_energy_inelastic.setStyleSheet(style)
        self._txt_cutoff_energy_inelastic.setReadOnly(state)
        self._cb_cutoff_energy_inelastic.setEnabled(not state)

        self._lbl_cutoff_energy_bremsstrahlung.setStyleSheet(style)
        self._txt_cutoff_energy_bremsstrahlung.setReadOnly(state)
        self._cb_cutoff_energy_bremsstrahlung.setEnabled(not state)

        self._lbl_maximum_step_length.setStyleSheet(style)
        self._txt_maximum_step_length.setReadOnly(state)
        self._cb_maximum_step_length_unit.setEnabled(not state)

        self._tbl_forcing.setEnabled(not state)
        self._tlb_forcing.setVisible(not state)

    def isReadOnly(self):
        return _MaterialDialog.isReadOnly(self) and \
            self._txt_elastic_scattering_c1.isReadOnly() and \
            self._txt_elastic_scattering_c2.isReadOnly() and \
            self._txt_cutoff_energy_inelastic.isReadOnly() and \
            self._txt_cutoff_energy_bremsstrahlung.isReadOnly() and \
            self._txt_maximum_step_length.isReadOnly() and \
            not self._tbl_forcing.isEnabled() and \
            not self._tlb_forcing.isVisible()
예제 #41
0
class TemplateSelectDialog(QDialog):
    def refresh_templates_list(self):

        documents = documents_service.all_templates()

        self.model.removeRows(0, self.model.rowCount())

        if documents:
            for doc in sorted(list(documents), key=lambda d: d.filename):
                self._add_one_document(doc.filename, doc.template_document_id,
                                       doc.file_size, doc.description)

    def __init__(self, parent=None):
        super(TemplateSelectDialog, self).__init__(parent)

        self.setWindowTitle(_("Select a template"))

        self.template_id = []

        self.model = QStandardItemModel()
        self.view = QTableView()
        self.view.setModel(self.model)
        self.view.verticalHeader().setVisible(False)
        self.view.horizontalHeader().setVisible(False)
        self.view.setMinimumSize(500, 200)
        self.view.setShowGrid(True)
        self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.view.setSelectionBehavior(QAbstractItemView.SelectRows)

        l = QVBoxLayout()

        l.addWidget(QLabel(_("Please select one or more template.")))
        self.view.doubleClicked.connect(self._doubleClicked)

        l.addWidget(QLabel(u"<h3>{}</h3>".format(_("Documents Templates"))))
        l.addWidget(self.view)

        self.buttons = QDialogButtonBox()
        self.buttons.addButton(QDialogButtonBox.StandardButton.Cancel)
        self.buttons.addButton(QDialogButtonBox.Ok)
        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

        l.addWidget(self.buttons)

        self.setLayout(l)

    def _add_one_document(self, file_name, doc_id, file_size, description):
        """ Adds a document to the list
        """

        # file_name is either an absolute path or just a file name
        # If it is an absolute path, then the file is expected
        # to exist locally (at it absolute path location of course).
        # If not, then the file is expected to be a remote file
        # and shall be downloaded before opening.

        mainlog.debug(u"{} {} {} {}".format(file_name, doc_id, file_size,
                                            description))
        short_name = file_name
        if os.path.isabs(file_name):
            short_name = os.path.basename(file_name)
            if not os.path.isfile(file_name):
                raise Exception(u"The file {} doesn't exist".format(file_name))

        items = [QStandardItem(short_name)]
        items.append(QStandardItem(description))

        self.model.appendRow(items)
        self.model.setData(self.model.index(self.model.rowCount() - 1, 0),
                           doc_id, Qt.UserRole + 1)

        self.view.horizontalHeader().setResizeMode(0, QHeaderView.Stretch)
        self.view.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.view.resizeRowsToContents()

    @Slot()
    def accept(self):
        selected_rows = self.view.selectionModel().selectedRows()
        if selected_rows:
            self.template_id = []
            for row in selected_rows:
                ndx_row = row.row()
                self.template_id.append(
                    self.model.data(self.model.index(ndx_row, 0),
                                    Qt.UserRole + 1))
        else:
            self.template_id = []
        return super(TemplateSelectDialog, self).accept()

    @Slot()
    def reject(self):
        return super(TemplateSelectDialog, self).reject()

    @Slot(QModelIndex)
    def _doubleClicked(self, ndx):
        self.accept()
예제 #42
0
class FindOrderDialog(QDialog):
    def __init__(self,parent):
        global dao
        super(FindOrderDialog,self).__init__(parent)

        title = _("Find order")
        self.setWindowTitle(title)
        top_layout = QVBoxLayout()
        self.title_widget = TitleWidget(title,self)
        top_layout.addWidget(self.title_widget)

        hlayout = QHBoxLayout()
        hlayout.addWidget(QLabel(_("Search")))
        self.search_criteria = QLineEdit()
        self.search_criteria.setObjectName("search_criteria")
        hlayout.addWidget(self.search_criteria)
        top_layout.addLayout(hlayout)



        self.search_results_view = QTableView()

        self.headers_view = QHeaderView(Qt.Orientation.Horizontal)
        self.header_model = make_header_model([_("Preorder Nr"),_("Order Nr"),_("Customer Nr"),_("Customer"),_("Order Part")])
        self.headers_view.setModel(self.header_model) # qt's doc : The view does *not* take ownership (bt there's something with the selecion mode

        self.search_results_model = QStandardItemModel()
        self.search_results_view.setModel(self.search_results_model)

        self.search_results_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.search_results_view.setHorizontalHeader(self.headers_view)
        self.search_results_view.verticalHeader().hide()
        # self.search_results_view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
        self.search_results_view.horizontalHeader().setResizeMode(3, QHeaderView.Stretch)
        self.search_results_view.horizontalHeader().setResizeMode(4, QHeaderView.Stretch)

        self.search_results_view.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.buttons = QDialogButtonBox()
        self.buttons.addButton( QDialogButtonBox.StandardButton.Cancel)
        self.buttons.addButton( QDialogButtonBox.Ok)
        self.buttons.button(QDialogButtonBox.Ok).setObjectName("go_search")

        top_layout.addWidget(self.search_results_view)
        top_layout.setStretch(2,1000)
        top_layout.addWidget(self.buttons)
        self.setLayout(top_layout)

        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)
        self.search_results_view.activated.connect(self.row_activated)
        self.search_criteria.returnPressed.connect(self.search_criteria_submitted)

        self.setMinimumSize(800,640)

    def find_by_text(self,text):
        text = text.strip()

        try:
            too_many_results, res = dao.order_part_dao.find_ids_by_text(text.strip())

            if too_many_results:
                showWarningBox(_("Too many results"),_("The query you've given brought back too many results. Only a part of them is displayed. Consider refining your query"),object_name="too_many_results")

            return dao.order_part_dao.find_by_ids(res)

        except DataException as de:

            if de.code == DataException.CRITERIA_IS_EMPTY:
                showErrorBox(_("Error in the filter !"),
                             _("The filter can't be empty"),object_name="filter_is_empty")
            elif de.code == DataException.CRITERIA_IS_TOO_SHORT:
                showErrorBox(_("Error in the filter !"),
                             _("The filter is too short"),object_name="filter_is_too_short")
            elif de.code == DataException.CRITERIA_IS_TOO_LONG:
                showErrorBox(_("Error in the filter !"),
                             _("The filter is too long"),object_name="filter_is_too_long")

            return []
        


        # order_part_match = []
        # matches = []
        # super_matches = []

        # import re
        # re_order_part_identifier = re.compile("^([0-9]+)([A-Z]+)$")
        # re_label_identifier = re.compile("^[0-9]+$")

        # if re_order_part_identifier.match(text.upper()):
        #     # Look for an exact (and unique) match on the order part full identifier
        #     p = dao.order_part_dao.find_by_full_id(text.upper())
        #     if p:
        #         # Mimick SQLAlchemy's KeyTuples
        #         # FIXME It seems that I use something that's internal to SQLA
        #         # Search SQLA's doc for KeyedTuple to find about collections.namedtuple()

        #         from sqlalchemy.util._collections import KeyedTuple

        #         kt = KeyedTuple([p.order_id, p.order.preorder_label, p.order.accounting_label, p.order.customer_order_name, p.order.customer.fullname, p.order.creation_date, p.description, p.order_part_id, p.label],
        #                         labels=['order_id','preorder_label','accounting_label','customer_order_name','fullname','creation_date','description','order_part_id','label'])

        #         order_part_match = [ kt ]

        # if re_label_identifier.match(text):
        #     for r in dao.order_dao.find_by_labels(int(text)):
        #         super_matches.append(r)

        # for r in dao.order_dao.find_by_customer_name(text):
        #     # mainlog.debug('customer name match on {}'.format(text))
        #     matches.append(r)

        # for r in dao.order_dao.find_by_customer_order_name(text):
        #     # mainlog.debug('customer name match on {}'.format(text))
        #     matches.append(r)

        # for r in dao.order_part_dao.find_by_description(text):
        #     matches.append(r)

        # # Finally we order the matches to bring the most relevant
        # # first. The "most relevant" is really a business order.

        # return order_part_match + super_matches + \
        #     sorted(matches, lambda a,b: - cmp(a.order_id,b.order_id))


    def _search_results_to_array(self,search_results):
        array = []
        
        for res in search_results:
            # mainlog.debug("_search_results_to_array {}".format(res.creation_date))

            i = QStandardItem(res.preorder_part_label)
            row = [i,
                   QStandardItem(res.accounting_part_label),
                   QStandardItem(res.customer_order_name),
                   QStandardItem(res.fullname)]

            if 'order_part_id' in res.__dict__:
                # It's an order part

                i.setData( res.order_part_id, Qt.UserRole)
                i.setData( 'order_part', Qt.UserRole+1)
                row.append( QStandardItem(res.description))
            else:
                # It's an order

                i.setData( res.order_id, Qt.UserRole)
                i.setData( 'order', Qt.UserRole+1)
                row.append( QStandardItem())

            array.append(row)

        return array


    def load_search_results(self,text=None):
        global dao

        if text is None:
            text = self.search_criteria.text()

        db_results = self.find_by_text(text)
        array = self._search_results_to_array(db_results)

        self.search_results_model.removeRows(0,self.search_results_model.rowCount())
        for row in array:
            self.search_results_model.appendRow(row)
        mainlog.debug("Loaded model : {}".format(self.search_results_model.rowCount()))
        self.search_results_view.resizeColumnsToContents()

        if self.search_results_model.rowCount() > 0:
            self.search_results_view.setCurrentIndex(self.search_results_model.index(0,0))
            self.search_results_view.setFocus(Qt.OtherFocusReason)

        if self.search_results_model.rowCount() == 1:
            self.accept()


    def selected_item(self):
        mainlog.debug("FindOrder.selected_item")
        ndx = self.search_results_view.currentIndex()
        if ndx.isValid():
            ndx = self.search_results_view.model().index( ndx.row(), 0)

            item = ndx.data(Qt.UserRole)
            item_type = ndx.data(Qt.UserRole+1)

            if item_type == 'order':
                mainlog.debug("FindOrder.selected_item order_id={}".format(item))
                return dao.order_dao.find_by_id(item)
            elif item_type == 'order_part':
                mainlog.debug("FindOrder.selected_item order_part_id={}".format(item))
                return dao.order_part_dao.find_by_id(item)
            else:
                mainlog.error("Unsupported item type {}".format(item_type))
        else:
            mainlog.error("Invalid index")
            return None

    @Slot()
    def accept(self):
        # mainlog.debug("accept")
        # self.load_search_results()
        # mainlog.debug("accept - done")
        return super(FindOrderDialog,self).accept()

    @Slot()
    def reject(self):
        return super(FindOrderDialog,self).reject()

    @Slot()
    def search_criteria_submitted(self):
        mainlog.debug("search_criteria_submitted")
        self.load_search_results()

    @Slot(QModelIndex)
    def row_activated(self,ndx):
        mainlog.debug("row_activated")
        self.accept()

    def keyPressEvent(self,event):

        # The goal here is to make sure the accept signal is called only
        # if the user clicks on the "OK" button /with the mouse/ and,
        # not with the keyboard

        if event.key() in (Qt.Key_Enter, Qt.Key_Return):
            return
        else:
            super(FindOrderDialog,self).keyPressEvent(event)