class WeekViewWidget(SubFrame): def __init__(self, parent): super(WeekViewWidget, self).__init__("Week", None, parent) self._table_model = QStandardItemModel(1, 2, None) self._table_model.setHorizontalHeaderLabels( [_("# Ord."), _("Customer")]) self.table_view = LeftRightTableView(self) self.table_view.setModel(self._table_model) self.table_view.verticalHeader().hide() self.table_view.setAlternatingRowColors(True) self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.table_view.setSelectionMode(QAbstractItemView.SingleSelection) self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_view.horizontalHeader().setResizeMode( 0, QHeaderView.ResizeToContents) self.table_view.horizontalHeader().setStretchLastSection(True) self.preorder_brush = QBrush(QColor(255, 255, 128)) self.completed_order_brush = QBrush(QColor(128, 255, 128)) self.layout().addWidget(self.table_view) def _set_last_row(self, data, role): for i in range(self._table_model.columnCount()): self._table_model.setData( self._table_model.index(self._table_model.rowCount() - 1, i), data, role) def set_data(self, data, base_date): self.set_title(date_to_dm(base_date)) self._table_model.removeRows(0, self._table_model.rowCount()) current_ndx = 0 for d in data: order, customer_name = d number = order.preorder_label if order.accounting_label: number = order.accounting_label self._table_model.appendRow( [QStandardItem(str(number)), QStandardItem(customer_name)]) self._table_model.setData(self._table_model.index(current_ndx, 0), order.order_id, Qt.UserRole) if order.state == OrderStatusType.order_completed: self._set_last_row(self.completed_order_brush, Qt.BackgroundRole) elif order.state == OrderStatusType.preorder_definition: self._set_last_row(self.preorder_brush, Qt.BackgroundRole) current_ndx += 1 # Not the slightest idea why this works # and not resizeColumnsToContents for i in range(self._table_model.columnCount()): self.table_view.resizeColumnToContents(i)
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)])
class FilteredTable(QWidget): 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)
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()
class DialogLookup(QtGui.QDialog): def __init__(self, lookup): super().__init__() self._lookup = lookup self._model = QStandardItemModel() # (4, 4) self.initUI() self.initDB() def initUI(self): global _compatible self.result = userCancelled # create our window # define window xLoc,yLoc,xDim,yDim self.setGeometry(250, 250, 640, 480) self.setWindowTitle(translate('Rocket', "Component lookup...")) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) searchLabel = QtGui.QLabel(translate('Rocket', "Search"), self) self._searchInput = QtGui.QLineEdit(self) self._searchInput.setFixedWidth(80) self._searchInput.textEdited.connect(self.onSearch) lookupTypeLabel = QtGui.QLabel(translate('Rocket', "Component"), self) self._lookupTypeCombo = QtGui.QComboBox(self) self._lookupTypeCombo.addItems(_compatible[self._lookup]) self._lookupTypeCombo.setCurrentText(self._lookup) self._lookupTypeCombo.currentTextChanged.connect(self.onLookupType) self._dbTable = QtGui.QTableView(self) self._dbTable.setModel(self._model) self._dbTable.setSelectionBehavior(QtGui.QTableView.SelectRows) self._dbTable.setSelectionMode(QtGui.QTableView.SingleSelection) self._dbTable.setSortingEnabled(True) self._dbTable.doubleClicked.connect(self.onTableDoubleClick) # cancel button cancelButton = QtGui.QPushButton('Cancel', self) cancelButton.clicked.connect(self.onCancel) cancelButton.setAutoDefault(True) # OK button okButton = QtGui.QPushButton('OK', self) okButton.setDefault(True) okButton.clicked.connect(self.onOk) layout = QVBoxLayout() line = QHBoxLayout() line.addWidget(searchLabel) line.addWidget(self._searchInput) line.addStretch() line.addWidget(lookupTypeLabel) line.addWidget(self._lookupTypeCombo) layout.addLayout(line) layout.addWidget(self._dbTable) line = QHBoxLayout() line.addStretch() line.addWidget(okButton) line.addWidget(cancelButton) layout.addLayout(line) self.setLayout(layout) # now make the window visible self.show() def initDB(self): self._connection = sqlite3.connect( "file:" + FreeCAD.getUserAppDataDir() + "Mod/Rocket/Resources/parts/Parts.db?mode=ro", uri=True) self._connection.row_factory = sqlite3.Row self._updateModel() def onLookupType(self, value): self._updateModel() def onSearch(self, value): rows = [] value = str(value).strip() if len(value) > 0: for column in range(self._model.columnCount()): items = self._model.findItems(value, Qt.MatchContains, column) for item in items: row = item.row() if not row in rows: rows.append(row) for row in range(self._model.rowCount()): if row in rows: self._dbTable.showRow(row) else: self._dbTable.hideRow(row) else: for row in range(self._model.rowCount()): self._dbTable.showRow(row) def onTableDoubleClick(self, selected): self.result = self._getSelected(selected.row()) self.close() def onCancel(self): self.result = {} self.close() def onOk(self): selected = self._dbTable.selectedIndexes() if len(selected) > 0: row = selected[0].row() self.result = self._getSelected(row) else: self.result = {} self.close() def _getSelectedBodyTube(self, row): try: index = int(self._model.item(row, 0).text()) cone = getBodyTube(self._connection, index) return cone except NotFoundError: _err(translate('Rocket', "Body tube not found")) except MultipleEntryError: _err(translate('Rocket', "Multiple identical entries found")) return {} def _getSelectedNose(self, row): try: index = int(self._model.item(row, 0).text()) cone = getNoseCone(self._connection, index) return cone except NotFoundError: _err(translate('Rocket', "Nose cone not found")) except MultipleEntryError: _err(translate('Rocket', "Multiple identical entries found")) return {} def _getSelectedTransition(self, row): try: index = int(self._model.item(row, 0).text()) tran = getTransition(self._connection, index) return tran except NotFoundError: _err(translate('Rocket', "Transition not found")) except MultipleEntryError: _err(translate('Rocket', "Multiple identical entries found")) return {} def _getSelected(self, row): queryType = str(self._lookupTypeCombo.currentText()) if queryType == COMPONENT_TYPE_ANY: query = self._lookup else: query = queryType if query in [ COMPONENT_TYPE_BODYTUBE, COMPONENT_TYPE_COUPLER, COMPONENT_TYPE_ENGINEBLOCK, COMPONENT_TYPE_LAUNCHLUG, COMPONENT_TYPE_CENTERINGRING, COMPONENT_TYPE_BULKHEAD ]: return self._getSelectedBodyTube(row) elif query == COMPONENT_TYPE_NOSECONE: return self._getSelectedNose(row) elif query == COMPONENT_TYPE_TRANSITION: return self._getSelectedTransition(row) # elif query == COMPONENT_TYPE_PARACHUTE: # pass # elif query == COMPONENT_TYPE_STREAMER: # pass return {} def _itemWithDimension(self, value, dim): return self._newItem(_valueWithUnits(value, dim)) def _newItem(self, text): item = QStandardItem(text) item.setEditable(False) return item def _queryBodyTube(self, queryType): rows = listBodyTubes(self._connection, queryType) self._model.setRowCount(len(rows)) if queryType == COMPONENT_TYPE_BULKHEAD: self._model.setColumnCount(7) else: self._model.setColumnCount(8) self._dbTable.hideColumn(0) # This holds index for lookups self._dbTable.setVerticalHeader(None) # Add the column headers self._model.setHorizontalHeaderItem( 1, self._newItem(translate('Rocket', "Type"))) self._model.setHorizontalHeaderItem( 2, self._newItem(translate('Rocket', "Manufacturer"))) self._model.setHorizontalHeaderItem( 3, self._newItem(translate('Rocket', "Part Number"))) self._model.setHorizontalHeaderItem( 4, self._newItem(translate('Rocket', "Description"))) self._model.setHorizontalHeaderItem( 5, self._newItem(translate('Rocket', "Outer Diameter"))) if queryType == COMPONENT_TYPE_BULKHEAD: self._model.setHorizontalHeaderItem( 6, self._newItem(translate('Rocket', "Length"))) else: self._model.setHorizontalHeaderItem( 6, self._newItem(translate('Rocket', "Inner Diameter"))) self._model.setHorizontalHeaderItem( 7, self._newItem(translate('Rocket', "Length"))) rowCount = 0 for row in rows: self._model.setItem(rowCount, 0, self._newItem(str(row["body_tube_index"]))) self._model.setItem(rowCount, 1, self._newItem(str(row["type"]))) self._model.setItem(rowCount, 2, self._newItem(str(row["manufacturer"]))) self._model.setItem(rowCount, 3, self._newItem(str(row["part_number"]))) self._model.setItem(rowCount, 4, self._newItem(str(row["description"]))) self._model.setItem( rowCount, 5, self._newItem( self._itemWithDimension(row["outer_diameter"], row["outer_diameter_units"]))) if queryType == COMPONENT_TYPE_BULKHEAD: self._model.setItem( rowCount, 6, self._newItem( self._itemWithDimension(row["length"], row["length_units"]))) else: self._model.setItem( rowCount, 6, self._newItem( self._itemWithDimension(row["inner_diameter"], row["inner_diameter_units"]))) self._model.setItem( rowCount, 7, self._newItem( self._itemWithDimension(row["length"], row["length_units"]))) rowCount += 1 def _queryNoseCone(self): rows = listNoseCones(self._connection) self._model.setRowCount(len(rows)) self._model.setColumnCount(9) self._dbTable.hideColumn(0) # This holds index for lookups self._dbTable.setVerticalHeader(None) # Add the column headers self._model.setHorizontalHeaderItem( 1, self._newItem(translate('Rocket', "Manufacturer"))) self._model.setHorizontalHeaderItem( 2, self._newItem(translate('Rocket', "Part Number"))) self._model.setHorizontalHeaderItem( 3, self._newItem(translate('Rocket', "Description"))) self._model.setHorizontalHeaderItem( 4, self._newItem(translate('Rocket', "Diameter"))) self._model.setHorizontalHeaderItem( 5, self._newItem(translate('Rocket', "Length"))) self._model.setHorizontalHeaderItem( 6, self._newItem(translate('Rocket', "Shoulder Diameter"))) self._model.setHorizontalHeaderItem( 7, self._newItem(translate('Rocket', "Shoulder Length"))) self._model.setHorizontalHeaderItem( 8, self._newItem(translate('Rocket', "Shape"))) rowCount = 0 for row in rows: self._model.setItem(rowCount, 0, self._newItem(str(row["nose_index"]))) self._model.setItem(rowCount, 1, self._newItem(str(row["manufacturer"]))) self._model.setItem(rowCount, 2, self._newItem(str(row["part_number"]))) self._model.setItem(rowCount, 3, self._newItem(str(row["description"]))) self._model.setItem( rowCount, 4, self._newItem( self._itemWithDimension(row["diameter"], row["diameter_units"]))) self._model.setItem( rowCount, 5, self._newItem( self._itemWithDimension(row["length"], row["length_units"]))) self._model.setItem( rowCount, 6, self._newItem( self._itemWithDimension(row["shoulder_diameter"], row["shoulder_diameter_units"]))) self._model.setItem( rowCount, 7, self._newItem( self._itemWithDimension(row["shoulder_length"], row["shoulder_length_units"]))) self._model.setItem(rowCount, 8, self._newItem(str(row["shape"]))) rowCount += 1 def _queryTransition(self): rows = listTransitions(self._connection) self._model.setRowCount(len(rows)) self._model.setColumnCount(12) self._dbTable.hideColumn(0) # This holds index for lookups self._dbTable.setVerticalHeader(None) # Add the column headers self._model.setHorizontalHeaderItem( 1, self._newItem(translate('Rocket', "Manufacturer"))) self._model.setHorizontalHeaderItem( 2, self._newItem(translate('Rocket', "Part Number"))) self._model.setHorizontalHeaderItem( 3, self._newItem(translate('Rocket', "Description"))) self._model.setHorizontalHeaderItem( 4, self._newItem(translate('Rocket', "Fore Diameter"))) self._model.setHorizontalHeaderItem( 5, self._newItem(translate('Rocket', "Aft Diameter"))) self._model.setHorizontalHeaderItem( 6, self._newItem(translate('Rocket', "Length"))) self._model.setHorizontalHeaderItem( 7, self._newItem(translate('Rocket', "Fore Shoulder Diameter"))) self._model.setHorizontalHeaderItem( 8, self._newItem(translate('Rocket', "Fore Shoulder Length"))) self._model.setHorizontalHeaderItem( 9, self._newItem(translate('Rocket', "Aft Shoulder Diameter"))) self._model.setHorizontalHeaderItem( 10, self._newItem(translate('Rocket', "Aft Shoulder Length"))) self._model.setHorizontalHeaderItem( 11, self._newItem(translate('Rocket', "Shape"))) rowCount = 0 for row in rows: self._model.setItem(rowCount, 0, self._newItem(str(row["transition_index"]))) self._model.setItem(rowCount, 1, self._newItem(str(row["manufacturer"]))) self._model.setItem(rowCount, 2, self._newItem(str(row["part_number"]))) self._model.setItem(rowCount, 3, self._newItem(str(row["description"]))) self._model.setItem( rowCount, 4, self._newItem( self._itemWithDimension( row["fore_outside_diameter"], row["fore_outside_diameter_units"]))) self._model.setItem( rowCount, 5, self._newItem( self._itemWithDimension( row["aft_outside_diameter"], row["aft_outside_diameter_units"]))) self._model.setItem( rowCount, 6, self._newItem( self._itemWithDimension(row["length"], row["length_units"]))) self._model.setItem( rowCount, 7, self._newItem( self._itemWithDimension( row["fore_shoulder_diameter"], row["fore_shoulder_diameter_units"]))) self._model.setItem( rowCount, 8, self._newItem( self._itemWithDimension( row["fore_shoulder_length"], row["fore_shoulder_length_units"]))) self._model.setItem( rowCount, 9, self._newItem( self._itemWithDimension( row["aft_shoulder_diameter"], row["aft_shoulder_diameter_units"]))) self._model.setItem( rowCount, 10, self._newItem( self._itemWithDimension(row["aft_shoulder_length"], row["aft_shoulder_length_units"]))) self._model.setItem(rowCount, 11, self._newItem(str(row["shape"]))) rowCount += 1 def _updateModel(self): queryType = str(self._lookupTypeCombo.currentText()) if queryType == COMPONENT_TYPE_ANY: query = self._lookup else: query = queryType if query in [ COMPONENT_TYPE_BODYTUBE, COMPONENT_TYPE_COUPLER, COMPONENT_TYPE_ENGINEBLOCK, COMPONENT_TYPE_LAUNCHLUG, COMPONENT_TYPE_CENTERINGRING, COMPONENT_TYPE_BULKHEAD ]: self._queryBodyTube(queryType) elif query == COMPONENT_TYPE_NOSECONE: self._queryNoseCone() elif query == COMPONENT_TYPE_TRANSITION: self._queryTransition() # elif query == COMPONENT_TYPE_PARACHUTE: # pass # elif query == COMPONENT_TYPE_STREAMER: # pass def update(self): # Update the SQL query pass
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()
class ReprintDeliverySlipDialog(QDialog): def __init__(self, parent, dao): super(ReprintDeliverySlipDialog, self).__init__(parent) self.dao = dao title = _("Print a delivery slip") self.setWindowTitle(title) top_layout = QVBoxLayout() self.title_widget = TitleWidget(title, None) self.buttons = QDialogButtonBox() self.buttons.addButton(QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton(QDialogButtonBox.Ok) hlayout = QHBoxLayout() hlayout.addWidget(QLabel(_("Slip number"))) self.slip_number = QLineEdit() hlayout.addWidget(self.slip_number) hlayout.addStretch() self.search_results_view = QTableView() self.search_results_model = QStandardItemModel() self.search_results_model.setHorizontalHeaderLabels( [_("Slip Nr"), _("Date"), _("Customer"), _("Order")]) self.search_results_view.setModel(self.search_results_model) # self.search_results_view.setHorizontalHeader(self.headers_view) self.search_results_view.setEditTriggers( QAbstractItemView.NoEditTriggers) self.search_results_view.horizontalHeader().setResizeMode( 1, QHeaderView.ResizeToContents) self.search_results_view.horizontalHeader().setResizeMode( 2, QHeaderView.Stretch) self.search_results_view.verticalHeader().hide() self.slip_part_view = DeliverySlipViewWidget(self) hlayout_results = QHBoxLayout() hlayout_results.addWidget(self.search_results_view) hlayout_results.addWidget(self.slip_part_view) self.search_results_model.removeRows( 0, self.search_results_model.rowCount()) delivery_slips = self.dao.delivery_slip_part_dao.find_recent() for slip in delivery_slips: self.search_results_model.appendRow([ QStandardItem(str(slip[0])), QStandardItem(date_to_dmy(slip[1])), QStandardItem(slip[2]), QStandardItem(slip[3]) ]) top_layout.addWidget(self.title_widget) top_layout.addLayout(hlayout) top_layout.addLayout(hlayout_results) top_layout.addWidget(self.buttons) top_layout.setStretch(2, 100) self.setLayout(top_layout) self.search_results_view.setSelectionBehavior( QAbstractItemView.SelectRows) self.search_results_view.setSelectionMode( QAbstractItemView.SingleSelection) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) self.search_results_view.activated.connect(self.row_activated) self.search_results_view.selectionModel().currentRowChanged.connect( self.row_selected) @Slot(QModelIndex, QModelIndex) def row_selected(self, cur_ndx, prev_ndx): slip_id = cur_ndx.model().index(cur_ndx.row(), 0).data() self.slip_number.setText(str(slip_id)) self.slip_part_view.set_delivery_slip_parts( dao.delivery_slip_part_dao.load_slip_parts_frozen(slip_id)) @Slot(QModelIndex) def row_activated(self, ndx): slip_id = ndx.model().index(ndx.row(), 0).data() self.slip_number.setText(str(slip_id)) self.accept() @Slot() def accept(self): try: try: slip_id = int(self.slip_number.text()) except ValueError as e: makeErrorBox( _("The delivery slip number {} is not valid").format( self.slip_number.text())).exec_() return if self.dao.delivery_slip_part_dao.id_exists(slip_id): print_delivery_slip(self.dao, slip_id) else: makeErrorBox( _("The delivery slip {} doesn't exist").format( slip_id)).exec_() return except Exception as e: mainlog.exception(e) msgBox = makeErrorBox(_("Something wrong happened while printing")) msgBox.exec_() return super(ReprintDeliverySlipDialog, self).accept() @Slot() def reject(self): return super(ReprintDeliverySlipDialog, self).reject()
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)