X-Git-Url: https://git.phdru.name/?a=blobdiff_plain;f=m_librarian%2Fwx%2FListBooks.py;h=fcf7eab52c9b7d3d112872a5dabab0f9a58105a0;hb=8de27024bcd0eb7d8dbede490368a68261204955;hp=b027de006e89282b5bf6821979c34b598221c05d;hpb=e98603cf1bd1a7a5ae24d96a3ad69e21a26ff67a;p=m_librarian.git diff --git a/m_librarian/wx/ListBooks.py b/m_librarian/wx/ListBooks.py index b027de0..fcf7eab 100644 --- a/m_librarian/wx/ListBooks.py +++ b/m_librarian/wx/ListBooks.py @@ -1,40 +1,119 @@ # 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 .Grids import GridWindow, GridPanel +_ = getattr(translations, 'ugettext', None) or translations.gettext + + +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 SetValue(self, row, col, value): + self.data[row][col] = value + + # Optional methods + + # Called when the grid needs to display labels + def GetRowLabelValue(self, row): + return str(row) + + def GetColLabelValue(self, col): + return _(self.column_names[col]) + + # 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 + + # 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 + + 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.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(total_rows, len(columns)) + grid.SetTable( + BooksDataTable(total_rows+1, columns), + takeOwnership=True, + ) grid.EnableEditing(False) - for row in range(total_rows): - 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 + 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, 0, wx.ALIGN_LEFT, wx. ALIGN_CENTRE) - grid.SetCellSize(row, 0, 1, len(columns)) - grid.SetCellValue(row, 0, u'%s' % (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 @@ -44,26 +123,57 @@ class ListBooksPanel(GridPanel): value = book.series else: value = u'Вне серий' - grid.SetCellAlignment(row, 0, + grid.SetCellAlignment(row, 1, wx.ALIGN_LEFT, wx. ALIGN_CENTRE) - grid.SetCellSize(row, 0, 1, len(columns)) - grid.SetCellValue(row, 0, + 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): + 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, 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): - pass + if event.GetCol() == 0: + return + self.toggleCB(event.GetRow()) def OnKeyDown(self, event): if event.GetKeyCode() == wx.WXK_ESCAPE: @@ -71,9 +181,41 @@ class ListBooksPanel(GridPanel): 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()