1# -*- coding: utf-8 -*-
2
3# Copyright(C) 2013 Julien Veyssier
4#
5# This file is part of weboob.
6#
7# weboob is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Lesser General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# weboob is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Lesser General Public License for more details.
16#
17# You should have received a copy of the GNU Lesser General Public License
18# along with weboob. If not, see <http://www.gnu.org/licenses/>.
19
20import os
21
22from PyQt5.QtCore import Qt, pyqtSlot as Slot
23from PyQt5.QtGui import QKeySequence
24from PyQt5.QtWidgets import QApplication, QFrame, QShortcut
25
26from weboob.capabilities.base import NotAvailable
27from weboob.capabilities.cinema import CapCinema
28from weboob.capabilities.torrent import CapTorrent
29from weboob.capabilities.subtitle import CapSubtitle
30from weboob.tools.application.qt5 import QtMainWindow, QtDo
31from weboob.tools.application.qt5.backendcfg import BackendCfg
32from weboob.tools.application.qt5.models import BackendListModel
33from weboob.tools.application.qt5.search_history import HistoryCompleter
34from weboob.tools.compat import unicode
35
36from weboob.applications.suboob.suboob import LANGUAGE_CONV
37from weboob.applications.qcineoob.ui.main_window_ui import Ui_MainWindow
38from weboob.applications.qcineoob.ui.result_ui import Ui_Result
39
40from .minimovie import MiniMovie
41from .miniperson import MiniPerson
42from .minitorrent import MiniTorrent
43from .minisubtitle import MiniSubtitle
44from .movie import Movie
45from .person import Person
46from .torrent import Torrent
47from .subtitle import Subtitle
48
49MAX_TAB_TEXT_LENGTH=30
50
51class Result(QFrame):
52    def __init__(self, weboob, app, parent=None):
53        super(Result, self).__init__(parent)
54        self.ui = Ui_Result()
55        self.ui.setupUi(self)
56
57        self.parent = parent
58        self.weboob = weboob
59        self.app = app
60        self.minis = []
61        self.current_info_widget = None
62
63        # action history is composed by the last action and the action list
64        # An action is a function, a list of arguments and a description string
65        self.action_history = {'last_action': None, 'action_list': []}
66        self.ui.backButton.clicked.connect(self.doBack)
67        self.ui.backButton.setShortcut(QKeySequence('Alt+Left'))
68        self.ui.backButton.hide()
69
70    def doAction(self, description, fun, args):
71        ''' Call fun with args as arguments
72        and save it in the action history
73        '''
74        self.ui.currentActionLabel.setText(description)
75        if self.action_history['last_action'] is not None:
76            self.action_history['action_list'].append(self.action_history['last_action'])
77            self.ui.backButton.setToolTip('%s (Alt+Left)'%self.action_history['last_action']['description'])
78            self.ui.backButton.show()
79        self.action_history['last_action'] = {'function': fun, 'args': args, 'description': description}
80        # manage tab text
81        mytabindex = self.parent.ui.resultsTab.indexOf(self)
82        tabtxt = description
83        if len(tabtxt) > MAX_TAB_TEXT_LENGTH:
84            tabtxt = '%s...'%tabtxt[:MAX_TAB_TEXT_LENGTH]
85        self.parent.ui.resultsTab.setTabText(mytabindex, tabtxt)
86        self.parent.ui.resultsTab.setTabToolTip(mytabindex, description)
87        return fun(*args)
88
89    @Slot()
90    def doBack(self):
91        ''' Go back in action history
92        Basically call previous function and update history
93        '''
94        if len(self.action_history['action_list']) > 0:
95            todo = self.action_history['action_list'].pop()
96            self.ui.currentActionLabel.setText(todo['description'])
97            self.action_history['last_action'] = todo
98            if len(self.action_history['action_list']) == 0:
99                self.ui.backButton.hide()
100            else:
101                self.ui.backButton.setToolTip(self.action_history['action_list'][-1]['description'])
102            # manage tab text
103            mytabindex = self.parent.ui.resultsTab.indexOf(self)
104            tabtxt = todo['description']
105            if len(tabtxt) > MAX_TAB_TEXT_LENGTH:
106                tabtxt = '%s...'%tabtxt[:MAX_TAB_TEXT_LENGTH]
107            self.parent.ui.resultsTab.setTabText(mytabindex, tabtxt)
108            self.parent.ui.resultsTab.setTabToolTip(mytabindex, todo['description'])
109
110            return todo['function'](*todo['args'])
111
112    def castingAction(self, backend_name, id, role):
113        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
114        for mini in self.minis:
115            self.ui.list_content.layout().removeWidget(mini)
116            mini.hide()
117            mini.deleteLater()
118
119        self.minis = []
120        self.parent.ui.searchEdit.setEnabled(False)
121        QApplication.setOverrideCursor(Qt.WaitCursor)
122
123        self.process = QtDo(self.weboob, self.addPerson, fb=self.processFinished)
124        self.process.do('iter_movie_persons', id, role, backends=backend_name, caps=CapCinema)
125        self.parent.ui.stopButton.show()
126
127    def moviesInCommonAction(self, backend_name, id1, id2):
128        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
129        for mini in self.minis:
130            self.ui.list_content.layout().removeWidget(mini)
131            mini.hide()
132            mini.deleteLater()
133
134        self.minis = []
135        self.parent.ui.searchEdit.setEnabled(False)
136        QApplication.setOverrideCursor(Qt.WaitCursor)
137
138        for a_backend in self.weboob.iter_backends():
139            if (backend_name and a_backend.name == backend_name):
140                backend = a_backend
141                person1 = backend.get_person(id1)
142                person2 = backend.get_person(id2)
143
144        lid1 = []
145        for p in backend.iter_person_movies_ids(id1):
146            lid1.append(p)
147        lid2 = []
148        for p in backend.iter_person_movies_ids(id2):
149            lid2.append(p)
150
151        inter = list(set(lid1) & set(lid2))
152
153        chrono_list = []
154        for common in inter:
155            movie = backend.get_movie(common)
156            movie.backend = backend_name
157            role1 = movie.get_roles_by_person_id(person1.id)
158            role2 = movie.get_roles_by_person_id(person2.id)
159            if (movie.release_date != NotAvailable):
160                year = movie.release_date.year
161            else:
162                year = '????'
163            movie.short_description = '(%s) %s as %s ; %s as %s'%(year , person1.name, ', '.join(role1), person2.name, ', '.join(role2))
164            i = 0
165            while (i<len(chrono_list) and movie.release_date != NotAvailable and
166                  (chrono_list[i].release_date == NotAvailable or year > chrono_list[i].release_date.year)):
167                i += 1
168            chrono_list.insert(i, movie)
169
170        for movie in chrono_list:
171            self.addMovie(movie)
172
173        self.processFinished()
174
175    def personsInCommonAction(self, backend_name, id1, id2):
176        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
177        for mini in self.minis:
178            self.ui.list_content.layout().removeWidget(mini)
179            mini.hide()
180            mini.deleteLater()
181
182        self.minis = []
183        self.parent.ui.searchEdit.setEnabled(False)
184        QApplication.setOverrideCursor(Qt.WaitCursor)
185
186        for a_backend in self.weboob.iter_backends():
187            if (backend_name and a_backend.name == backend_name):
188                backend = a_backend
189                movie1 = backend.get_movie(id1)
190                movie2 = backend.get_movie(id2)
191
192        lid1 = []
193        for p in backend.iter_movie_persons_ids(id1):
194            lid1.append(p)
195        lid2 = []
196        for p in backend.iter_movie_persons_ids(id2):
197            lid2.append(p)
198
199        inter = list(set(lid1) & set(lid2))
200
201        for common in inter:
202            person = backend.get_person(common)
203            person.backend = backend_name
204            role1 = movie1.get_roles_by_person_id(person.id)
205            role2 = movie2.get_roles_by_person_id(person.id)
206            person.short_description = '%s in %s ; %s in %s'%(', '.join(role1), movie1.original_title, ', '.join(role2), movie2.original_title)
207            self.addPerson(person)
208
209        self.processFinished()
210
211    def filmographyAction(self, backend_name, id, role):
212        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
213        for mini in self.minis:
214            self.ui.list_content.layout().removeWidget(mini)
215            mini.hide()
216            mini.deleteLater()
217
218        self.minis = []
219        self.parent.ui.searchEdit.setEnabled(False)
220        QApplication.setOverrideCursor(Qt.WaitCursor)
221
222        self.process = QtDo(self.weboob, self.addMovie, fb=self.processFinished)
223        self.process.do('iter_person_movies', id, role, backends=backend_name, caps=CapCinema)
224        self.parent.ui.stopButton.show()
225
226    def search(self, tosearch, pattern, lang):
227        if tosearch == 'person':
228            self.searchPerson(pattern)
229        elif tosearch == 'movie':
230            self.searchMovie(pattern)
231        elif tosearch == 'torrent':
232            self.searchTorrent(pattern)
233        elif tosearch == 'subtitle':
234            self.searchSubtitle(lang, pattern)
235
236    def searchMovie(self, pattern):
237        if not pattern:
238            return
239        self.doAction(u'Search movie "%s"' % pattern, self.searchMovieAction, [pattern])
240
241    def searchMovieAction(self, pattern):
242        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
243        for mini in self.minis:
244            self.ui.list_content.layout().removeWidget(mini)
245            mini.hide()
246            mini.deleteLater()
247
248        self.minis = []
249        self.parent.ui.searchEdit.setEnabled(False)
250        QApplication.setOverrideCursor(Qt.WaitCursor)
251
252        backend_name = self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex())
253
254        self.process = QtDo(self.weboob, self.addMovie, fb=self.processFinished)
255        #self.process.do('iter_movies', pattern, backends=backend_name, caps=CapCinema)
256        self.process.do(self.app._do_complete, self.parent.getCount(), ('original_title'), 'iter_movies', pattern, backends=backend_name, caps=CapCinema)
257        self.parent.ui.stopButton.show()
258
259    def addMovie(self, movie):
260        minimovie = MiniMovie(self.weboob, self.weboob[movie.backend], movie, self)
261        self.ui.list_content.layout().insertWidget(self.ui.list_content.layout().count()-1,minimovie)
262        self.minis.append(minimovie)
263
264    def displayMovie(self, movie, backend):
265        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
266        if self.current_info_widget is not None:
267            self.ui.info_content.layout().removeWidget(self.current_info_widget)
268            self.current_info_widget.hide()
269            self.current_info_widget.deleteLater()
270        wmovie = Movie(movie, backend, self)
271        self.ui.info_content.layout().addWidget(wmovie)
272        self.current_info_widget = wmovie
273        QApplication.restoreOverrideCursor()
274
275    def searchPerson(self, pattern):
276        if not pattern:
277            return
278        self.doAction(u'Search person "%s"' % pattern, self.searchPersonAction, [pattern])
279
280    def searchPersonAction(self, pattern):
281        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
282        for mini in self.minis:
283            self.ui.list_content.layout().removeWidget(mini)
284            mini.hide()
285            mini.deleteLater()
286
287        self.minis = []
288        self.parent.ui.searchEdit.setEnabled(False)
289        QApplication.setOverrideCursor(Qt.WaitCursor)
290
291        backend_name = self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex())
292
293        self.process = QtDo(self.weboob, self.addPerson, fb=self.processFinished)
294        #self.process.do('iter_persons', pattern, backends=backend_name, caps=CapCinema)
295        self.process.do(self.app._do_complete, self.parent.getCount(), ('name'), 'iter_persons', pattern, backends=backend_name, caps=CapCinema)
296        self.parent.ui.stopButton.show()
297
298    def addPerson(self, person):
299        miniperson = MiniPerson(self.weboob, self.weboob[person.backend], person, self)
300        self.ui.list_content.layout().insertWidget(self.ui.list_content.layout().count()-1,miniperson)
301        self.minis.append(miniperson)
302
303    def displayPerson(self, person, backend):
304        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
305        if self.current_info_widget is not None:
306            self.ui.info_content.layout().removeWidget(self.current_info_widget)
307            self.current_info_widget.hide()
308            self.current_info_widget.deleteLater()
309        wperson = Person(person, backend, self)
310        self.ui.info_content.layout().addWidget(wperson)
311        self.current_info_widget = wperson
312        QApplication.restoreOverrideCursor()
313
314    def searchTorrent(self, pattern):
315        if not pattern:
316            return
317        self.doAction(u'Search torrent "%s"' % pattern, self.searchTorrentAction, [pattern])
318
319    def searchTorrentAction(self, pattern):
320        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
321        for mini in self.minis:
322            self.ui.list_content.layout().removeWidget(mini)
323            mini.hide()
324            mini.deleteLater()
325
326        self.minis = []
327        self.parent.ui.searchEdit.setEnabled(False)
328        QApplication.setOverrideCursor(Qt.WaitCursor)
329
330        backend_name = self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex())
331
332        self.process = QtDo(self.weboob, self.addTorrent, fb=self.processFinished)
333        #self.process.do('iter_torrents', pattern, backends=backend_name, caps=CapTorrent)
334        self.process.do(self.app._do_complete, self.parent.getCount(), ('name'), 'iter_torrents', pattern, backends=backend_name, caps=CapTorrent)
335        self.parent.ui.stopButton.show()
336
337    def processFinished(self):
338        self.parent.ui.searchEdit.setEnabled(True)
339        QApplication.restoreOverrideCursor()
340        self.process = None
341        self.parent.ui.stopButton.hide()
342
343    @Slot()
344    def stopProcess(self):
345        if self.process is not None:
346            self.process.stop()
347
348    def addTorrent(self, torrent):
349        minitorrent = MiniTorrent(self.weboob, self.weboob[torrent.backend], torrent, self)
350        positionToInsert = self.ui.list_content.layout().count()-1
351        # if possible, we insert the torrent keeping a sort by seed
352        if torrent.seeders != NotAvailable:
353            seeders = torrent.seeders
354            positionToInsert = 0
355            while positionToInsert < len(self.minis) and\
356            (self.minis[positionToInsert].torrent.seeders != NotAvailable and\
357                    seeders <= self.minis[positionToInsert].torrent.seeders):
358                positionToInsert += 1
359
360        self.ui.list_content.layout().insertWidget(positionToInsert, minitorrent)
361        self.minis.insert(positionToInsert, minitorrent)
362
363    def displayTorrent(self, torrent, backend):
364        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
365        if self.current_info_widget is not None:
366            self.ui.info_content.layout().removeWidget(self.current_info_widget)
367            self.current_info_widget.hide()
368            self.current_info_widget.deleteLater()
369        wtorrent = Torrent(torrent, backend, self)
370        self.ui.info_content.layout().addWidget(wtorrent)
371        self.current_info_widget = wtorrent
372
373    def searchSubtitle(self, lang, pattern):
374        if not pattern:
375            return
376        self.doAction(u'Search subtitle "%s" (lang:%s)' % (pattern, lang), self.searchSubtitleAction, [lang, pattern])
377
378    def searchSubtitleAction(self, lang, pattern):
379        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
380        for mini in self.minis:
381            self.ui.list_content.layout().removeWidget(mini)
382            mini.hide()
383            mini.deleteLater()
384
385        self.minis = []
386        self.parent.ui.searchEdit.setEnabled(False)
387        QApplication.setOverrideCursor(Qt.WaitCursor)
388
389        backend_name = self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex())
390
391        self.process = QtDo(self.weboob, self.addSubtitle, fb=self.processFinished)
392        #self.process.do('iter_subtitles', lang, pattern, backends=backend_name, caps=CapSubtitle)
393        self.process.do(self.app._do_complete, self.parent.getCount(), ('name'), 'iter_subtitles', lang, pattern, backends=backend_name, caps=CapSubtitle)
394        self.parent.ui.stopButton.show()
395
396    def addSubtitle(self, subtitle):
397        minisubtitle = MiniSubtitle(self.weboob, self.weboob[subtitle.backend], subtitle, self)
398        self.ui.list_content.layout().insertWidget(self.ui.list_content.layout().count()-1,minisubtitle)
399        self.minis.append(minisubtitle)
400
401    def displaySubtitle(self, subtitle, backend):
402        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
403        if self.current_info_widget is not None:
404            self.ui.info_content.layout().removeWidget(self.current_info_widget)
405            self.current_info_widget.hide()
406            self.current_info_widget.deleteLater()
407        wsubtitle = Subtitle(subtitle, backend, self)
408        self.ui.info_content.layout().addWidget(wsubtitle)
409        self.current_info_widget = wsubtitle
410
411    def searchId(self, id, stype):
412        QApplication.setOverrideCursor(Qt.WaitCursor)
413        title_field = 'name'
414        if stype == 'movie':
415            cap = CapCinema
416            title_field = 'original_title'
417        elif stype == 'person':
418            cap = CapCinema
419        elif stype == 'torrent':
420            cap = CapTorrent
421        elif stype == 'subtitle':
422            cap = CapSubtitle
423        if '@' in id:
424            backend_name = id.split('@')[1]
425            id = id.split('@')[0]
426        else:
427            backend_name = None
428        for backend in self.weboob.iter_backends():
429            if backend.has_caps(cap) and ((backend_name and backend.name == backend_name) or not backend_name):
430                object = getattr(backend, 'get_%s' % stype)(id)
431                if object:
432                    func_name = 'display' + stype[0].upper() + stype[1:]
433                    func = getattr(self, func_name)
434                    title = getattr(object, title_field)
435                    self.doAction('Details of %s %r' % (stype, title), func, [object, backend])
436
437        QApplication.restoreOverrideCursor()
438
439
440class MainWindow(QtMainWindow):
441    def __init__(self, config, weboob, app, parent=None):
442        super(MainWindow, self).__init__(parent)
443        self.ui = Ui_MainWindow()
444        self.ui.setupUi(self)
445
446        self.config = config
447        self.weboob = weboob
448        self.app = app
449
450        # search history is a list of patterns which have been searched
451        history_path = os.path.join(self.weboob.workdir, 'qcineoob_history')
452        qc = HistoryCompleter(history_path, self)
453        qc.load()
454        qc.setCaseSensitivity(Qt.CaseInsensitive)
455        self.ui.searchEdit.setCompleter(qc)
456
457        self.ui.searchEdit.returnPressed.connect(self.search)
458        self.ui.idEdit.returnPressed.connect(self.searchId)
459        self.ui.typeCombo.currentIndexChanged[unicode].connect(self.typeComboChanged)
460
461        count = self.config.get('settings', 'maxresultsnumber')
462        self.ui.countSpin.setValue(int(count))
463        showT = self.config.get('settings', 'showthumbnails')
464        self.ui.showTCheck.setChecked(showT == '1')
465
466        self.ui.stopButton.hide()
467
468        self.ui.actionBackends.triggered.connect(self.backendsConfig)
469        q = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q), self)
470        q.activated.connect(self.close)
471        n = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_PageDown), self)
472        n.activated.connect(self.nextTab)
473        p = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_PageUp), self)
474        p.activated.connect(self.prevTab)
475        w = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_W), self)
476        w.activated.connect(self.closeCurrentTab)
477
478        l = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_L), self)
479        l.activated.connect(self.ui.searchEdit.setFocus)
480        l.activated.connect(self.ui.searchEdit.selectAll)
481
482        self.ui.resultsTab.tabCloseRequested.connect(self.closeTab)
483
484        self.loadBackendsList()
485
486        if self.ui.backendEdit.count() == 0:
487            self.backendsConfig()
488
489        langs = sorted(LANGUAGE_CONV.keys())
490        for lang in langs:
491            self.ui.langCombo.addItem(lang)
492        self.ui.langCombo.hide()
493        self.ui.langLabel.hide()
494
495    @Slot(int)
496    def closeTab(self, index):
497        if self.ui.resultsTab.widget(index) != 0:
498            self.ui.resultsTab.removeTab(index)
499
500    @Slot()
501    def closeCurrentTab(self):
502        self.closeTab(self.ui.resultsTab.currentIndex())
503
504    @Slot()
505    def prevTab(self):
506        index = self.ui.resultsTab.currentIndex() - 1
507        size = self.ui.resultsTab.count()
508        if size != 0:
509            self.ui.resultsTab.setCurrentIndex(index % size)
510
511    @Slot()
512    def nextTab(self):
513        index = self.ui.resultsTab.currentIndex() + 1
514        size = self.ui.resultsTab.count()
515        if size != 0:
516            self.ui.resultsTab.setCurrentIndex(index % size)
517
518    def newTab(self, txt, backend, person=None, movie=None, torrent=None, subtitle=None):
519        id = ''
520        if person is not None:
521            id = person.id
522            stype = 'person'
523        elif movie is not None:
524            id = movie.id
525            stype = 'movie'
526        elif subtitle is not None:
527            id = subtitle.id
528            stype = 'subtitle'
529        elif torrent is not None:
530            id = torrent.id
531            stype = 'torrent'
532        new_res = Result(self.weboob, self.app, self)
533        self.ui.stopButton.clicked.connect(new_res.stopProcess)
534        tabtxt = txt
535        if len(tabtxt) > MAX_TAB_TEXT_LENGTH:
536            tabtxt = '%s...'%tabtxt[:MAX_TAB_TEXT_LENGTH]
537        index = self.ui.resultsTab.addTab(new_res, tabtxt)
538        self.ui.resultsTab.setTabToolTip(index, txt)
539        new_res.searchId(id, stype)
540
541    @Slot()
542    def search(self):
543        pattern = self.ui.searchEdit.text()
544        self.ui.searchEdit.completer().addString(pattern)
545
546        tosearch = self.ui.typeCombo.currentText()
547        lang = self.ui.langCombo.currentText()
548        new_res = Result(self.weboob, self.app, self)
549
550        txt = 'search %s "%s"'%(tosearch, pattern)
551        tabtxt = txt
552        if len(tabtxt) > MAX_TAB_TEXT_LENGTH:
553            tabtxt = '%s...'%tabtxt[:MAX_TAB_TEXT_LENGTH]
554        index = self.ui.resultsTab.addTab(new_res, tabtxt)
555        self.ui.resultsTab.setTabToolTip(index, txt)
556
557        self.ui.resultsTab.setCurrentWidget(new_res)
558        new_res.search(tosearch, pattern, lang)
559
560    @Slot()
561    def searchId(self):
562        id = self.ui.idEdit.text()
563        stype = self.ui.idTypeCombo.currentText()
564        new_res = Result(self.weboob, self.app, self)
565        self.ui.resultsTab.addTab(new_res, id)
566        self.ui.resultsTab.setCurrentWidget(new_res)
567        new_res.searchId(id, stype)
568
569    @Slot()
570    def backendsConfig(self):
571        bckndcfg = BackendCfg(self.weboob, (CapCinema, CapTorrent, CapSubtitle,), self)
572        if bckndcfg.run():
573            self.loadBackendsList()
574
575    def loadBackendsList(self):
576        model = BackendListModel(self.weboob)
577        model.addBackends()
578        self.ui.backendEdit.setModel(model)
579
580        current_backend = self.config.get('settings', 'backend')
581        idx = self.ui.backendEdit.findData(current_backend)
582        if idx >= 0:
583            self.ui.backendEdit.setCurrentIndex(idx)
584
585        if self.ui.backendEdit.count() == 0:
586            self.ui.searchEdit.setEnabled(False)
587        else:
588            self.ui.searchEdit.setEnabled(True)
589
590    @Slot(unicode)
591    def typeComboChanged(self, value):
592        if value == 'subtitle':
593            self.ui.langCombo.show()
594            self.ui.langLabel.show()
595        else:
596            self.ui.langCombo.hide()
597            self.ui.langLabel.hide()
598
599    def getCount(self):
600        num = self.ui.countSpin.value()
601        if num == 0:
602            return None
603        else:
604            return num
605
606    def closeEvent(self, ev):
607        self.config.set('settings', 'backend', self.ui.backendEdit.itemData(
608            self.ui.backendEdit.currentIndex()))
609        self.ui.searchEdit.completer().save()
610        self.config.set('settings', 'maxresultsnumber', self.ui.countSpin.value())
611        self.config.set('settings', 'showthumbnails', '1' if self.ui.showTCheck.isChecked() else '0')
612
613        self.config.save()
614        ev.accept()
615