X-Git-Url: https://git.phdru.name/?a=blobdiff_plain;ds=sidebyside;f=m_librarian%2Fwx%2FListBooks.py;h=fcf7eab52c9b7d3d112872a5dabab0f9a58105a0;hb=8de27024bcd0eb7d8dbede490368a68261204955;hp=955ef851782e3c40653b9d8fdacc0cf4edc79c20;hpb=f3860aa18c077dbffc5fcc876f0f2aba49509305;p=m_librarian.git diff --git a/m_librarian/wx/ListBooks.py b/m_librarian/wx/ListBooks.py index 955ef85..fcf7eab 100644 --- a/m_librarian/wx/ListBooks.py +++ b/m_librarian/wx/ListBooks.py @@ -1,79 +1,221 @@ # coding: utf-8 -import wx +import wx, wx.grid # noqa: E401 multiple imports on one line from ..compat import string_type, unicode_type +from ..download import download from ..translations import translations -from .AWindow import AWindow +from .Grids import GridWindow, GridPanel -class ListBooksWindow(AWindow): +_ = getattr(translations, 'ugettext', None) or translations.gettext - session_config_section_name = 'list_books' - window_title = u"m_Librarian: Список книг" - def __init__(self, parent, books_by_author): - self.books_by_author = books_by_author - AWindow.__init__(self, parent) +class BooksDataTable(wx.grid.GridTableBase): + def __init__(self, rows_count, column_names): + wx.grid.GridTableBase.__init__(self) + self.rows_count = rows_count + self.column_names = column_names + self.data = [] + for row in range(rows_count + 1): + row_data = [] + self.data.append(row_data) + for col in range(len(column_names)): + row_data.append('') + + # required methods for the wxPyGridTableBase interface + + def GetNumberRows(self): + return self.rows_count + + def GetNumberCols(self): + return len(self.column_names) + + def IsEmptyCell(self, row, col): + return False + + # Get/Set values in the table. The Python version of these + # methods can handle any data-type, (as long as the Editor and + # Renderer understands the type too,) not just strings as in the + # C++ version. + def GetValue(self, row, col): + return self.data[row][col] - def OnInit(self): - AWindow.OnInit(self) - ListBooksPanel(self, self.books_by_author) + def SetValue(self, row, col, value): + self.data[row][col] = value + # Optional methods -class ListBooksPanel(wx.Panel): + # Called when the grid needs to display labels + def GetRowLabelValue(self, row): + return str(row) - def __init__(self, parent, books_by_author): - wx.Panel.__init__(self, parent) - self.books_by_author = books_by_author + def GetColLabelValue(self, col): + return _(self.column_names[col]) - list_books_sizer = wx.BoxSizer(wx.VERTICAL) - self.SetSizer(list_books_sizer) + # Called to determine the kind of editor/renderer to use by + # default, doesn't necessarily have to be the same type used + # natively by the editor/renderer if they know how to convert. + def GetTypeName(self, row, col): + if col == 0: + return wx.grid.GRID_VALUE_BOOL + else: + return wx.grid.GRID_VALUE_STRING - self.grid = grid = wx.grid.Grid(self) - list_books_sizer.Add(grid, 0, wx.EXPAND, 0) + # Called to determine how the data can be fetched and stored by the + # editor and renderer. This allows you to enforce some type-safety + # in the grid. + def CanGetValueAs(self, row, col, typeName): + colType = self.GetTypeName(row, col) + if typeName == colType: + return True + else: + return False - self.InitGrid() + def CanSetValueAs(self, row, col, typeName): + return self.CanGetValueAs(row, col, typeName) + + +class ListBooksPanel(GridPanel): def InitGrid(self): - _ = getattr(translations, 'ugettext', None) or translations.gettext - books_by_author = self.books_by_author['books_by_author'] - columns = self.books_by_author['columns'] - author = next(iter(books_by_author)) - books = books_by_author[author] - series = {book.series for book in books} + books_by_author = self.param['books_by_author'] + columns = self.param['columns'] + columns.insert(0, u'Выбрать') + total_rows = 0 + for author in books_by_author: + books = books_by_author[author] + series = {book.series for book in books} + total_rows += len(books) + len(series) + 1 grid = self.grid - grid.CreateGrid(len(books) + len(series), len(columns)) + grid.SetTable( + BooksDataTable(total_rows+1, columns), + takeOwnership=True, + ) grid.EnableEditing(False) - for row in range(len(books)): - grid.SetRowLabelValue(row, str(row)) - grid.AutoSizeRowLabelSize(row) for col, col_name in enumerate(columns): - grid.SetColLabelValue(col, _(col_name)) grid.AutoSizeColLabelSize(col) - if col_name in ('ser_no', 'size'): + if col == 0: + cell_attr = wx.grid.GridCellAttr() + cell_attr.SetAlignment(wx.ALIGN_CENTRE, wx. ALIGN_CENTRE) + grid.SetColAttr(col, cell_attr) + elif col_name in ('ser_no', 'size'): cell_attr = wx.grid.GridCellAttr() cell_attr.SetAlignment(wx.ALIGN_RIGHT, wx. ALIGN_CENTRE) grid.SetColAttr(col, cell_attr) row = 0 - series = None - for book in books: - if book.series != series: - if book.series: - value = book.series - else: - value = u'Вне серий' - grid.SetCellAlignment(row, 0, wx.ALIGN_LEFT, wx. ALIGN_CENTRE) - grid.SetCellSize(row, 0, 1, len(columns)) - grid.SetCellValue(row, 0, u'%s — %s' % (book.author1, value)) - row += 1 - series = book.series - for col, col_name in enumerate(columns): - value = getattr(book, col_name) - if value is None: - value = u'' - elif not isinstance(value, (string_type, unicode_type)): - value = str(value) - grid.SetCellValue(row, col, value) + grid.SetCellAlignment(row, 1, wx.ALIGN_CENTRE, wx. ALIGN_CENTRE) + grid.SetCellSize(row, 1, 1, len(columns)-1) + row = 1 + self.book_by_row = book_by_row = {} # map {row: book} + self.toggle_rows = toggle_rows = {} # map {row: [list of subrows]} + for author in sorted(books_by_author): + grid.SetCellAlignment(row, 1, wx.ALIGN_LEFT, wx. ALIGN_CENTRE) + grid.SetCellSize(row, 1, 1, len(columns)-1) + grid.SetCellValue(row, 1, u'%s' % (author,)) + author_row = row + toggle_rows[author_row] = [] row += 1 + books = books_by_author[author] + series = None + for book in books: + if book.series != series: + if book.series: + value = book.series + else: + value = u'Вне серий' + grid.SetCellAlignment(row, 1, + wx.ALIGN_LEFT, wx. ALIGN_CENTRE) + grid.SetCellSize(row, 1, 1, len(columns)-1) + grid.SetCellValue(row, 1, + u'%s — %s' % (book.author1, value)) + series_row = row + toggle_rows[author_row].append(row) + toggle_rows[series_row] = [] + row += 1 + series = book.series + for col, col_name in enumerate(columns[1:]): + value = getattr(book, col_name) + if value is None: + value = u'' + elif not isinstance(value, (string_type, unicode_type)): + value = str(value) + grid.SetCellValue(row, col+1, value) + book_by_row[row] = book + toggle_rows[author_row].append(row) + toggle_rows[series_row].append(row) + row += 1 + toggle_rows[0] = [row_ for row_ in range(1, row)] grid.AutoSizeColumns() grid.AutoSizeRows() + grid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnClick) + + search_button = wx.Button(self, label=u'Скачать') + self.GetSizer().Add(search_button, 0, wx.ALIGN_CENTER, 0) + search_button.Bind(wx.EVT_BUTTON, self.Download) + + def toggleCB(self, row): + value = self.grid.GetCellValue(row, 0) + if value: + value = '' + else: + value = '1' + self.grid.SetCellValue(row, 0, value) + toggle_rows = self.toggle_rows + if row in toggle_rows: + for row_ in toggle_rows[row]: + self.grid.SetCellValue(row_, 0, value) + + def OnClick(self, event): + if event.GetCol() > 0: + return + self.toggleCB(event.GetRow()) + + def OnDClick(self, event): + if event.GetCol() == 0: + return + self.toggleCB(event.GetRow()) + + def OnKeyDown(self, event): + if event.GetKeyCode() == wx.WXK_ESCAPE: + self.Parent.Close() + else: + event.Skip() + + def Download(self, event=None): + book_by_row = self.book_by_row + found_books = False + try: + for row in self.toggle_rows[0]: + value = self.grid.GetCellValue(row, 0) + if value and row in book_by_row: + found_books = True + download(book_by_row[row]) + except Exception as e: + self.report_error(str(e)) + else: + if not found_books: + self.report_error(u'Не выбрано книг для сохранения.') + + def report_error(self, error): + wx.MessageBox( + error, caption='m_Librarian download error', + style=wx.OK|wx.ICON_ERROR, parent=self.Parent) + + +class ListBooksWindow(GridWindow): + + session_config_section_name = 'list_books' + window_title = u"m_Librarian: Список книг" + GridPanelClass = ListBooksPanel + + def InitMenu(self): + GridWindow.InitMenu(self) + + download_menu = wx.Menu() + download = download_menu.Append(wx.ID_SAVE, + u"&Скачать", u"Скачать") + self.Bind(wx.EVT_MENU, self.OnDownload, download) + self.GetMenuBar().Append(download_menu, u"&Скачать") + + def OnDownload(self, event): + self.panel.Download()