]> git.phdru.name Git - m_librarian.git/blob - m_librarian/wx/ListBooks.py
Style(wx/books): Fix minor `flake8` warning
[m_librarian.git] / m_librarian / wx / ListBooks.py
1 # coding: utf-8
2
3 import wx, wx.grid  # noqa: E401 multiple imports on one line
4 from ..compat import string_type, unicode_type
5 from ..download import download
6 from ..translations import translations
7 from .Grids import GridWindow, GridPanel
8
9
10 _ = getattr(translations, 'ugettext', None) or translations.gettext
11
12
13 class BooksDataTable(wx.grid.GridTableBase):
14     def __init__(self, rows_count, column_names):
15         wx.grid.GridTableBase.__init__(self)
16         self.rows_count = rows_count
17         self.column_names = column_names
18         self.data = []
19         for row in range(rows_count + 1):
20             row_data = []
21             self.data.append(row_data)
22             for col in range(len(column_names)):
23                 row_data.append('')
24
25     # required methods for the wxPyGridTableBase interface
26
27     def GetNumberRows(self):
28         return self.rows_count
29
30     def GetNumberCols(self):
31         return len(self.column_names)
32
33     def IsEmptyCell(self, row, col):
34         return False
35
36     # Get/Set values in the table.  The Python version of these
37     # methods can handle any data-type, (as long as the Editor and
38     # Renderer understands the type too,) not just strings as in the
39     # C++ version.
40     def GetValue(self, row, col):
41         return self.data[row][col]
42
43     def SetValue(self, row, col, value):
44         self.data[row][col] = value
45
46     # Optional methods
47
48     # Called when the grid needs to display labels
49     def GetRowLabelValue(self, row):
50         return str(row)
51
52     def GetColLabelValue(self, col):
53         return _(self.column_names[col])
54
55     # Called to determine the kind of editor/renderer to use by
56     # default, doesn't necessarily have to be the same type used
57     # natively by the editor/renderer if they know how to convert.
58     def GetTypeName(self, row, col):
59         if col == 0:
60             return wx.grid.GRID_VALUE_BOOL
61         else:
62             return wx.grid.GRID_VALUE_STRING
63
64     # Called to determine how the data can be fetched and stored by the
65     # editor and renderer.  This allows you to enforce some type-safety
66     # in the grid.
67     def CanGetValueAs(self, row, col, typeName):
68         colType = self.GetTypeName(row, col)
69         if typeName == colType:
70             return True
71         else:
72             return False
73
74     def CanSetValueAs(self, row, col, typeName):
75         return self.CanGetValueAs(row, col, typeName)
76
77
78 class ListBooksPanel(GridPanel):
79
80     def InitGrid(self):
81         books_by_author = self.param['books_by_author']
82         columns = self.param['columns']
83         columns.insert(0, u'Выбрать')
84         total_rows = 0
85         for author in books_by_author:
86             books = books_by_author[author]
87             series = {book.series for book in books}
88             total_rows += len(books) + len(series) + 1
89         grid = self.grid
90         grid.SetTable(
91             BooksDataTable(total_rows+1, columns),
92             takeOwnership=True,
93         )
94         grid.EnableEditing(False)
95         for col, col_name in enumerate(columns):
96             grid.AutoSizeColLabelSize(col)
97             if col == 0:
98                 cell_attr = wx.grid.GridCellAttr()
99                 cell_attr.SetAlignment(wx.ALIGN_CENTRE, wx. ALIGN_CENTRE)
100                 grid.SetColAttr(col, cell_attr)
101             elif col_name in ('ser_no', 'size'):
102                 cell_attr = wx.grid.GridCellAttr()
103                 cell_attr.SetAlignment(wx.ALIGN_RIGHT, wx. ALIGN_CENTRE)
104                 grid.SetColAttr(col, cell_attr)
105         row = 0
106         grid.SetCellAlignment(row, 1, wx.ALIGN_CENTRE, wx. ALIGN_CENTRE)
107         grid.SetCellSize(row, 1, 1, len(columns)-1)
108         row = 1
109         self.book_by_row = book_by_row = {}  # map {row: book}
110         self.toggle_rows = toggle_rows = {}  # map {row: [list of subrows]}
111         for author in sorted(books_by_author):
112             grid.SetCellAlignment(row, 1, wx.ALIGN_LEFT, wx. ALIGN_CENTRE)
113             grid.SetCellSize(row, 1, 1, len(columns)-1)
114             grid.SetCellValue(row, 1, u'%s' % (author,))
115             author_row = row
116             toggle_rows[author_row] = []
117             row += 1
118             books = books_by_author[author]
119             series = None
120             for book in books:
121                 if book.series != series:
122                     if book.series:
123                         value = book.series
124                     else:
125                         value = u'Вне серий'
126                     grid.SetCellAlignment(row, 1,
127                                           wx.ALIGN_LEFT, wx. ALIGN_CENTRE)
128                     grid.SetCellSize(row, 1, 1, len(columns)-1)
129                     grid.SetCellValue(row, 1,
130                                       u'%s — %s' % (book.author1, value))
131                     series_row = row
132                     toggle_rows[author_row].append(row)
133                     toggle_rows[series_row] = []
134                     row += 1
135                     series = book.series
136                 for col, col_name in enumerate(columns[1:]):
137                     value = getattr(book, col_name)
138                     if value is None:
139                         value = u''
140                     elif not isinstance(value, (string_type, unicode_type)):
141                         value = str(value)
142                     grid.SetCellValue(row, col+1, value)
143                 book_by_row[row] = book
144                 toggle_rows[author_row].append(row)
145                 toggle_rows[series_row].append(row)
146                 row += 1
147         toggle_rows[0] = [row_ for row_ in range(1, row)]
148         grid.AutoSizeColumns()
149         grid.AutoSizeRows()
150         grid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnClick)
151
152         search_button = wx.Button(self, label=u'Скачать')
153         self.GetSizer().Add(search_button, 0, wx.ALIGN_CENTER, 0)
154         search_button.Bind(wx.EVT_BUTTON, self.Download)
155
156     def toggleCB(self, row):
157         value = self.grid.GetCellValue(row, 0)
158         if value:
159             value = ''
160         else:
161             value = '1'
162         self.grid.SetCellValue(row, 0, value)
163         toggle_rows = self.toggle_rows
164         if row in toggle_rows:
165             for row_ in toggle_rows[row]:
166                 self.grid.SetCellValue(row_, 0, value)
167
168     def OnClick(self, event):
169         if event.GetCol() > 0:
170             return
171         self.toggleCB(event.GetRow())
172
173     def OnDClick(self, event):
174         if event.GetCol() == 0:
175             return
176         self.toggleCB(event.GetRow())
177
178     def OnKeyDown(self, event):
179         if event.GetKeyCode() == wx.WXK_ESCAPE:
180             self.Parent.Close()
181         else:
182             event.Skip()
183
184     def Download(self, event=None):
185         book_by_row = self.book_by_row
186         found_books = False
187         try:
188             for row in self.toggle_rows[0]:
189                 value = self.grid.GetCellValue(row, 0)
190                 if value and row in book_by_row:
191                     found_books = True
192                     download(book_by_row[row])
193         except Exception as e:
194             self.report_error(str(e))
195         else:
196             if not found_books:
197                 self.report_error(u'Не выбрано книг для сохранения.')
198
199     def report_error(self, error):
200         wx.MessageBox(
201             error, caption='m_Librarian download error',
202             style=wx.OK | wx.ICON_ERROR, parent=self.Parent)
203
204
205 class ListBooksWindow(GridWindow):
206
207     session_config_section_name = 'list_books'
208     window_title = u"m_Librarian: Список книг"
209     GridPanelClass = ListBooksPanel
210
211     def InitMenu(self):
212         GridWindow.InitMenu(self)
213
214         download_menu = wx.Menu()
215         download = download_menu.Append(wx.ID_SAVE,
216                                         u"&Скачать", u"Скачать")
217         self.Bind(wx.EVT_MENU, self.OnDownload, download)
218         self.GetMenuBar().Append(download_menu, u"&Скачать")
219
220     def OnDownload(self, event):
221         self.panel.Download()