Пример #1
0
class ContactNotes(QWidget):
    """ Widget for storing notes about a contact """

    def __init__(self, weboob, contact, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Notes()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contact = contact

        self.ui.textEdit.setEnabled(False)
        self.ui.saveButton.setEnabled(False)
        self.process = QtDo(self.weboob, self._getNotes_cb, self._getNotes_eb)
        self.process.do('get_notes', self.contact.id, backends=(self.contact.backend,))

        self.connect(self.ui.saveButton, SIGNAL('clicked()'), self.saveNotes)

    def _getNotes_cb(self, backend, data):
        if not backend or not data:
            self.process = None
            self.ui.textEdit.setEnabled(True)
            self.ui.saveButton.setEnabled(True)
            return

        self.ui.textEdit.setText(data)

    def _getNotes_eb(self, backend, error, backtrace):
        if isinstance(error, NotImplementedError):
            return

        self.ui.textEdit.setEnabled(True)
        self.ui.saveButton.setEnabled(True)
        content = unicode(self.tr('Unable to load notes:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
            QMessageBox.critical(self, self.tr('Error while loading notes'),
            content, QMessageBox.Ok)

    def saveNotes(self):
        text = unicode(self.ui.textEdit.toPlainText())
        self.ui.saveButton.setEnabled(False)
        self.ui.textEdit.setEnabled(False)

        self.process = QtDo(self.weboob, self._saveNotes_cb, self._saveNotes_eb)
        self.process.do('save_notes', self.contact.id, text, backends=(self.contact.backend,))

    def _saveNotes_cb(self, backend, data):
        self.ui.saveButton.setEnabled(True)
        self.ui.textEdit.setEnabled(True)
        pass

    def _saveNotes_eb(self, backend, error, backtrace):
        self.ui.saveButton.setEnabled(True)
        self.ui.textEdit.setEnabled(True)
        content = unicode(self.tr('Unable to save notes:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
            QMessageBox.critical(self, self.tr('Error while saving notes'),
            content, QMessageBox.Ok)
Пример #2
0
    def addHousing(self, backend, housing):
        if not backend:
            self.ui.queriesList.setEnabled(True)
            self.ui.bookmarksButton.setEnabled(True)
            self.process = None
            return

        if not housing:
            return

        item = HousingListWidgetItem(housing)
        item.setAttrs(self.storage)

        if housing.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj', housing, ['photos'], backends=housing.backend)
            self.process_photo[housing.id] = process
        elif housing.photos is not NotAvailable and len(housing.photos) > 0:
            if not self.setPhoto(housing, item):
                photo = housing.photos[0]
                process = QtDo(self.weboob, lambda b, p: self.setPhoto(housing, item))
                process.do('fillobj', photo, ['data'], backends=housing.backend)
                self.process_photo[housing.id] = process

        self.ui.housingsList.addItem(item)

        if housing.fullid in self.process_bookmarks:
            self.process_bookmarks.pop(housing.fullid)
Пример #3
0
    def addHousing(self, backend, housing):
        if not backend:
            self.ui.queriesList.setEnabled(True)
            self.ui.bookmarksButton.setEnabled(True)
            self.process = None
            return

        if not housing:
            return

        item = HousingListWidgetItem(housing)
        item.setAttrs(self.storage)

        if housing.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj', housing, ['photos'], backends=housing.backend)
            self.process_photo[housing.id] = process
        elif housing.photos is not NotAvailable and len(housing.photos) > 0:
            if not self.setPhoto(housing, item):
                photo = housing.photos[0]
                process = QtDo(self.weboob, lambda b, p: self.setPhoto(housing, item))
                process.do('fillobj', photo, ['data'], backends=housing.backend)
                self.process_photo[housing.id] = process

        self.ui.housingsList.addItem(item)

        if housing.fullid in self.process_bookmarks:
            self.process_bookmarks.pop(housing.fullid)
Пример #4
0
    def gotEvent(self, event):
        found = False
        for i in xrange(self.ui.typeBox.count()):
            s = self.ui.typeBox.itemData(i)
            if s == event.type:
                found = True
        if not found:
            print(event.type)
            self.ui.typeBox.addItem(event.type.capitalize(), event.type)
            if event.type == self.event_filter:
                self.ui.typeBox.setCurrentIndex(self.ui.typeBox.count()-1)

        if self.event_filter and self.event_filter != event.type:
            return

        if not event.contact:
            return

        contact = event.contact
        contact.backend = event.backend
        status = ''

        if contact.status == contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        name = '<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' % (contact.name, status_color, status, event.backend)
        date = event.date.strftime('%Y-%m-%d %H:%M')
        type = event.type
        message = event.message

        item = QTreeWidgetItem(None, [name, date, type, message])
        item.setData(0, Qt.UserRole, event)
        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda c: self.setPhoto(c, item))
            process.do('fillobj', contact, ['photos'], backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob, lambda p: self.setPhoto(contact, item))
                process.do('fillobj', photo, ['thumbnail_data'], backends=contact.backend)
                self.photo_processes[contact.id] = process

        self.ui.eventsList.addTopLevelItem(item)
        self.ui.eventsList.resizeColumnToContents(0)
        self.ui.eventsList.resizeColumnToContents(1)
Пример #5
0
class ContactNotes(QWidget):
    """ Widget for storing notes about a contact """

    def __init__(self, weboob, contact, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Notes()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contact = contact

        self.ui.textEdit.setEnabled(False)
        self.ui.saveButton.setEnabled(False)

        def finished():
            self.process = None
            self.ui.textEdit.setEnabled(True)
            self.ui.saveButton.setEnabled(True)

        self.process = QtDo(self.weboob, self._getNotes_cb, self._getNotes_eb, finished)
        self.process.do('get_notes', self.contact.id, backends=(self.contact.backend,))

        self.connect(self.ui.saveButton, SIGNAL('clicked()'), self.saveNotes)

    def _getNotes_cb(self, data):
        if data:
            self.ui.textEdit.setText(data)

    def _getNotes_eb(self, backend, error, backtrace):
        if isinstance(error, NotImplementedError):
            return

        self.ui.textEdit.setEnabled(True)
        self.ui.saveButton.setEnabled(True)
        content = unicode(self.tr('Unable to load notes:\n%s\n')) % to_unicode(error)
        if logging.root.level <= logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
            QMessageBox.critical(self, self.tr('Error while loading notes'),
            content, QMessageBox.Ok)

    def saveNotes(self):
        text = unicode(self.ui.textEdit.toPlainText())
        self.ui.saveButton.setEnabled(False)
        self.ui.textEdit.setEnabled(False)

        self.process = QtDo(self.weboob, None, self._saveNotes_eb, self._saveNotes_fb)
        self.process.do('save_notes', self.contact.id, text, backends=(self.contact.backend,))

    def _saveNotes_fb(self):
        self.ui.saveButton.setEnabled(True)
        self.ui.textEdit.setEnabled(True)

    def _saveNotes_eb(self, backend, error, backtrace):
        content = unicode(self.tr('Unable to save notes:\n%s\n')) % to_unicode(error)
        if logging.root.level <= logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
            QMessageBox.critical(self, self.tr('Error while saving notes'),
            content, QMessageBox.Ok)
Пример #6
0
    def addContact(self, contact):
        if not contact:
            self.ui.refreshButton.setEnabled(True)
            return

        status = ''
        if contact.status == Contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == Contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == Contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        item = QListWidgetItem()
        item.setText(
            '<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' %
            (contact.name, status_color, status, contact.backend))
        item.setData(Qt.UserRole, contact)

        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj',
                       contact, ['photos'],
                       backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob,
                               lambda b, p: self.setPhoto(contact, item))
                process.do('fillobj',
                           photo, ['thumbnail_data'],
                           backends=contact.backend)
                self.photo_processes[contact.id] = process

        for i in xrange(self.ui.contactList.count()):
            if self.ui.contactList.item(i).data(
                    Qt.UserRole).toPyObject().status > contact.status:
                self.ui.contactList.insertItem(i, item)
                return

        self.ui.contactList.addItem(item)
Пример #7
0
class MiniVideo(QFrame):
    def __init__(self, weboob, backend, video, parent=None):
        QFrame.__init__(self, parent)
        self.ui = Ui_MiniVideo()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.backend = backend
        self.video = video
        self.ui.titleLabel.setText(video.title)
        self.ui.backendLabel.setText(backend.name)
        self.ui.durationLabel.setText(unicode(video.duration))
        self.ui.authorLabel.setText(unicode(video.author))
        self.ui.dateLabel.setText(video.date and unicode(video.date) or '')
        if video.rating_max:
            self.ui.ratingLabel.setText('%s / %s' %
                                        (video.rating, video.rating_max))
        else:
            self.ui.ratingLabel.setText('%s' % video.rating)

        self.process_thumbnail = QtDo(self.weboob, self.gotThumbnail)
        self.process_thumbnail.do('fillobj',
                                  self.video, ['thumbnail'],
                                  backends=backend)

    def gotThumbnail(self, backend, video):
        if not backend:
            return

        if video.thumbnail and video.thumbnail.data:
            img = QImage.fromData(video.thumbnail.data)
            self.ui.imageLabel.setPixmap(QPixmap.fromImage(img))

    def enterEvent(self, event):
        self.setFrameShadow(self.Sunken)
        QFrame.enterEvent(self, event)

    def leaveEvent(self, event):
        self.setFrameShadow(self.Raised)
        QFrame.leaveEvent(self, event)

    def mousePressEvent(self, event):
        QFrame.mousePressEvent(self, event)

        video = self.backend.get_video(self.video.id)
        if video:
            video_widget = Video(video, self)
            video_widget.show()
Пример #8
0
class MiniVideo(QFrame):
    def __init__(self, weboob, backend, video, parent=None):
        QFrame.__init__(self, parent)
        self.ui = Ui_MiniVideo()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.backend = backend
        self.video = video
        self.ui.titleLabel.setText(video.title)
        self.ui.backendLabel.setText(backend.name)
        self.ui.durationLabel.setText(unicode(video.duration))
        self.ui.authorLabel.setText(unicode(video.author))
        self.ui.dateLabel.setText(video.date and unicode(video.date) or '')
        if video.rating_max:
            self.ui.ratingLabel.setText('%s / %s' % (video.rating, video.rating_max))
        else:
            self.ui.ratingLabel.setText('%s' % video.rating)

        self.process_thumbnail = QtDo(self.weboob, self.gotThumbnail)
        self.process_thumbnail.do('fillobj', self.video, ['thumbnail'], backends=backend)

    def gotThumbnail(self, backend, video):
        if not backend:
            return

        if video.thumbnail and video.thumbnail.data:
            img = QImage.fromData(video.thumbnail.data)
            self.ui.imageLabel.setPixmap(QPixmap.fromImage(img))

    def enterEvent(self, event):
        self.setFrameShadow(self.Sunken)
        QFrame.enterEvent(self, event)

    def leaveEvent(self, event):
        self.setFrameShadow(self.Raised)
        QFrame.leaveEvent(self, event)

    def mousePressEvent(self, event):
        QFrame.mousePressEvent(self, event)

        video = self.backend.get_video(self.video.id)
        if video:
            video_widget = Video(video, self)
            video_widget.show()
Пример #9
0
class MetaGroup(IGroup):
    def iter_contacts(self, cb):
        if self.id == 'online':
            status = Contact.STATUS_ONLINE | Contact.STATUS_AWAY
        elif self.id == 'offline':
            status = Contact.STATUS_OFFLINE
        else:
            status = Contact.STATUS_ALL

        self.process = QtDo(self.weboob, lambda b, d: self.cb(cb, b, d))
        self.process.do('iter_contacts', status, caps=ICapContact)

    def cb(self, cb, backend, contact):
        if contact:
            cb(contact)
        elif not backend:
            self.process = None
            cb(None)
Пример #10
0
class MetaGroup(IGroup):
    def iter_contacts(self, cb):
        if self.id == 'online':
            status = Contact.STATUS_ONLINE|Contact.STATUS_AWAY
        elif self.id == 'offline':
            status = Contact.STATUS_OFFLINE
        else:
            status = Contact.STATUS_ALL

        self.process = QtDo(self.weboob, lambda b, d: self.cb(cb, b, d))
        self.process.do('iter_contacts', status, caps=ICapContact)

    def cb(self, cb, backend, contact):
        if contact:
            cb(contact)
        elif not backend:
            self.process = None
            cb(None)
Пример #11
0
    def addContact(self, contact):
        if not contact:
            self.ui.refreshButton.setEnabled(True)
            return

        status = ''
        if contact.status == Contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == Contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == Contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        item = QListWidgetItem()
        item.setText('<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' % (contact.name, status_color, status, contact.backend))
        item.setData(Qt.UserRole, contact)

        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj', contact, ['photos'], backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob, lambda b, p: self.setPhoto(contact, item))
                process.do('fillobj', photo, ['thumbnail_data'], backends=contact.backend)
                self.photo_processes[contact.id] = process

        for i in xrange(self.ui.contactList.count()):
            if self.ui.contactList.item(i).data(Qt.UserRole).toPyObject().status > contact.status:
                self.ui.contactList.insertItem(i, item)
                return

        self.ui.contactList.addItem(item)
Пример #12
0
class MetaGroup(IGroup):
    def iter_contacts(self, cb):
        if self.id == 'online':
            status = Contact.STATUS_ONLINE|Contact.STATUS_AWAY
        elif self.id == 'offline':
            status = Contact.STATUS_OFFLINE
        else:
            status = Contact.STATUS_ALL

        self.process = QtDo(self.weboob, lambda d: self.cb(cb, d), fb=lambda: self.fb(cb))
        self.process.do('iter_contacts', status, caps=CapContact)

    def cb(self, cb, contact):
        if contact:
            cb(contact)

    def fb(self, fb):
        self.process = None
        if fb:
            fb(None)
Пример #13
0
class MessagesManager(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_MessagesManager()
        self.ui.setupUi(self)

        self.weboob = weboob

        self.ui.backendsList.setCurrentRow(0)
        self.backend = None
        self.thread = None
        self.message = None

        self.ui.replyButton.setEnabled(False)
        self.ui.replyWidget.hide()

        self.connect(self.ui.backendsList, SIGNAL('itemSelectionChanged()'), self._backendChanged)
        self.connect(self.ui.threadsList,  SIGNAL('itemSelectionChanged()'), self._threadChanged)
        self.connect(self.ui.messagesTree, SIGNAL('itemClicked(QTreeWidgetItem *, int)'), self._messageSelected)
        self.connect(self.ui.messagesTree, SIGNAL('itemActivated(QTreeWidgetItem *, int)'), self._messageSelected)
        self.connect(self.ui.profileButton, SIGNAL('clicked()'), self._profilePressed)
        self.connect(self.ui.replyButton, SIGNAL('clicked()'), self._replyPressed)
        self.connect(self.ui.sendButton, SIGNAL('clicked()'), self._sendPressed)

    def load(self):
        self.ui.backendsList.clear()
        self.ui.backendsList.addItem('(All)')
        for backend in self.weboob.iter_backends():
            if not backend.has_caps(ICapMessages):
                continue

            item = QListWidgetItem(backend.name.capitalize())
            item.setData(Qt.UserRole, backend)
            self.ui.backendsList.addItem(item)

        self.refreshThreads()

    def _backendChanged(self):
        selection = self.ui.backendsList.selectedItems()
        if not selection:
            self.backend = None
            return

        self.backend = selection[0].data(Qt.UserRole).toPyObject()
        self.refreshThreads()

    def refreshThreads(self):
        self.ui.messagesTree.clear()
        self.ui.threadsList.clear()

        self.hideReply()
        self.ui.profileButton.hide()
        self.ui.replyButton.setEnabled(False)
        self.ui.backendsList.setEnabled(False)
        self.ui.threadsList.setEnabled(False)

        self.process_threads = QtDo(self.weboob, self._gotThread)
        self.process_threads.do('iter_threads', backends=self.backend, caps=ICapMessages)

    def _gotThread(self, backend, thread):
        if not backend:
            self.process_threads = None
            self.ui.backendsList.setEnabled(True)
            self.ui.threadsList.setEnabled(True)
            return

        item = QListWidgetItem(thread.title)
        item.setData(Qt.UserRole, (thread.backend, thread.id))
        self.ui.threadsList.addItem(item)

    def _threadChanged(self):
        self.ui.messagesTree.clear()
        selection = self.ui.threadsList.selectedItems()
        if not selection:
            return

        t = selection[0].data(Qt.UserRole).toPyObject()
        self.refreshThreadMessages(*t)

    def refreshThreadMessages(self, backend, id):
        self.ui.messagesTree.clear()
        self.ui.messageBody.clear()
        self.ui.backendsList.setEnabled(False)
        self.ui.threadsList.setEnabled(False)
        self.ui.replyButton.setEnabled(False)
        self.ui.profileButton.hide()
        self.hideReply()

        self.process = QtDo(self.weboob, self._gotThreadMessages)
        self.process.do('get_thread', id, backends=backend)

    def _gotThreadMessages(self, backend, thread):
        if thread is None:
            self.ui.backendsList.setEnabled(True)
            self.ui.threadsList.setEnabled(True)
            self.process = None
            return

        self.thread = thread
        if thread.flags & thread.IS_THREADS:
            top = self.ui.messagesTree.invisibleRootItem()
        else:
            top = None

        self._insert_message(thread.root, top)
        self.showMessage(thread.root)

        self.ui.messagesTree.expandAll()

    def _insert_message(self, message, top):
        item = QTreeWidgetItem(None, [message.title or '', message.sender or 'Unknown',
                                      time.strftime('%Y-%m-%d %H:%M:%S', message.date.timetuple())])
        item.setData(0, Qt.UserRole, message)
        if message.flags & message.IS_UNREAD:
            item.setForeground(0, QBrush(Qt.darkYellow))
            item.setForeground(1, QBrush(Qt.darkYellow))
            item.setForeground(2, QBrush(Qt.darkYellow))

        if top is not None:
            # threads
            top.addChild(item)
        else:
            # discussion
            self.ui.messagesTree.invisibleRootItem().insertChild(0, item)

        if message.children is not None:
            for child in message.children:
                self._insert_message(child, top and item)

    def _messageSelected(self, item, column):
        message = item.data(0, Qt.UserRole).toPyObject()

        self.showMessage(message, item)

    def showMessage(self, message, item=None):
        backend = self.weboob.get_backend(message.thread.backend)
        if backend.has_caps(ICapMessagesPost):
            self.ui.replyButton.setEnabled(True)
        self.message = message

        if message.title.startswith('Re:'):
            self.ui.titleEdit.setText(message.title)
        else:
            self.ui.titleEdit.setText('Re: %s' % message.title)

        if message.flags & message.IS_HTML:
            content = message.content
        else:
            content = message.content.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('\n', '<br />')

        extra = u''
        if message.flags & message.IS_NOT_RECEIVED:
            extra += u'<b>Status</b>: <font color=#ff0000>Unread</font><br />'
        elif message.flags & message.IS_RECEIVED:
            extra += u'<b>Status</b>: <font color=#00ff00>Read</font><br />'
        elif message.flags & message.IS_UNREAD:
            extra += u'<b>Status</b>: <font color=#0000ff>New</font><br />'

        self.ui.messageBody.setText("<h1>%s</h1>"
                                    "<b>Date</b>: %s<br />"
                                    "<b>From</b>: %s<br />"
                                    "%s"
                                    "<p>%s</p>"
                                    % (message.title, str(message.date), message.sender, extra, content))

        if item and message.flags & message.IS_UNREAD:
            backend.set_message_read(message)
            message.flags &= ~message.IS_UNREAD
            item.setForeground(0, QBrush())
            item.setForeground(1, QBrush())
            item.setForeground(2, QBrush())

        if message.thread.flags & message.thread.IS_DISCUSSION:
            self.ui.profileButton.show()
        else:
            self.ui.profileButton.hide()

    def _profilePressed(self):
        print self.thread.id
        self.emit(SIGNAL('display_contact'), self.thread.id)

    def displayReply(self):
        self.ui.replyButton.setText(self.tr('Cancel'))
        self.ui.replyWidget.show()

    def hideReply(self):
        self.ui.replyButton.setText(self.tr('Reply'))
        self.ui.replyWidget.hide()
        self.ui.replyEdit.clear()
        self.ui.titleEdit.clear()

    def _replyPressed(self):
        if self.ui.replyWidget.isVisible():
            self.hideReply()
        else:
            self.displayReply()

    def _sendPressed(self):
        if not self.ui.replyWidget.isVisible():
            return

        text = unicode(self.ui.replyEdit.toPlainText())
        title = unicode(self.ui.titleEdit.text())

        self.ui.backendsList.setEnabled(False)
        self.ui.threadsList.setEnabled(False)
        self.ui.messagesTree.setEnabled(False)
        self.ui.replyButton.setEnabled(False)
        self.ui.replyWidget.setEnabled(False)
        self.ui.sendButton.setText(self.tr('Sending...'))
        flags = 0
        if self.ui.htmlBox.currentIndex() == 0:
            flags = Message.IS_HTML
        m = Message(thread=self.thread,
                    id=0,
                    title=title,
                    sender=None,
                    receivers=None,
                    content=text,
                    parent=self.message,
                    flags=flags)
        self.process_reply = QtDo(self.weboob, self._postReply_cb, self._postReply_eb)
        self.process_reply.do('post_message', m, backends=self.thread.backend)

    def _postReply_cb(self, backend, ignored):
        if not backend:
            return

        self.ui.backendsList.setEnabled(True)
        self.ui.threadsList.setEnabled(True)
        self.ui.messagesTree.setEnabled(True)
        self.ui.replyButton.setEnabled(True)
        self.ui.replyWidget.setEnabled(True)
        self.ui.sendButton.setEnabled(True)
        self.ui.sendButton.setText(self.tr('Send'))
        self.hideReply()
        self.process_reply = None
        self.refreshThreadMessages(backend.name, self.thread.id)

    def _postReply_eb(self, backend, error, backtrace):
        content = unicode(self.tr('Unable to send message:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while posting reply'),
                             content, QMessageBox.Ok)
        self.ui.backendsList.setEnabled(True)
        self.ui.threadsList.setEnabled(True)
        self.ui.messagesTree.setEnabled(True)
        self.ui.replyButton.setEnabled(True)
        self.ui.replyWidget.setEnabled(True)
        self.ui.sendButton.setText(self.tr('Send'))
        self.process_reply = None
Пример #14
0
class Account(QFrame):
    def __init__(self, weboob, backend, parent=None):
        QFrame.__init__(self, parent)

        self.setFrameShape(QFrame.StyledPanel)
        self.setFrameShadow(QFrame.Raised)

        self.weboob = weboob
        self.backend = backend
        self.setLayout(QVBoxLayout())
        self.timer = None

        head = QHBoxLayout()
        headw = QWidget()
        headw.setLayout(head)

        self.title = QLabel(u'<h1>%s — %s</h1>' % (backend.name, backend.DESCRIPTION))
        self.body = QLabel()

        if backend.ICON:
            self.icon = QLabel()
            img = QImage(backend.ICON)
            self.icon.setPixmap(QPixmap.fromImage(img))
            head.addWidget(self.icon)

        head.addWidget(self.title)
        head.addStretch()

        self.layout().addWidget(headw)

        if backend.has_caps(ICapAccount):
            self.body.setText(u'<i>Waiting...</i>')
            self.layout().addWidget(self.body)

            self.timer = self.weboob.repeat(60, self.updateStats)

    def deinit(self):
        if self.timer is not None:
            self.weboob.stop(self.timer)

    def updateStats(self):
        self.process = QtDo(self.weboob, self.updateStats_cb, self.updateStats_eb)
        self.process.body = u''
        self.process.in_p = False
        self.process.do('get_account_status', backends=self.backend)

    def updateStats_cb(self, backend, field):
        if not field:
            if self.process.in_p:
                self.process.body += u"</p>"

            self.body.setText(self.process.body)

            self.process = None
            return

        if field.flags & StatusField.FIELD_HTML:
            value = u'%s' % field.value
        else:
            value = (u'%s' % field.value).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

        if field.flags & StatusField.FIELD_TEXT:
            if self.process.in_p:
                self.process.body += u'</p>'
            self.process.body += u'<p>%s</p>' % value
            self.process.in_p = False
        else:
            if not self.process.in_p:
                self.process.body += u"<p>"
                self.process.in_p = True
            else:
                self.process.body += u"<br />"

            self.process.body += u'<b>%s</b>: %s' % (field.label, field.value)

    def updateStats_eb(self, backend, err, backtrace):
        self.body.setText(u'<b>Unable to connect:</b> %s' % to_unicode(err))
        self.title.setText(u'<font color=#ff0000>%s</font>' % unicode(self.title.text()))
Пример #15
0
class MainWindow(QtMainWindow):
    def __init__(self, config, weboob, app, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.weboob = weboob
        self.app = app
        self.minis = []
        self.current_info_widget = None

        # search history is a list of patterns which have been searched
        self.search_history = self.loadSearchHistory()
        self.updateCompletion()

        # action history is composed by the last action and the action list
        # An action is a function, a list of arguments and a description string
        self.action_history = {'last_action': None, 'action_list': []}
        self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack)
        self.ui.backButton.hide()
        self.connect(self.ui.stopButton, SIGNAL("clicked()"), self.stopProcess)
        self.ui.stopButton.hide()

        self.connect(self.ui.searchEdit, SIGNAL("returnPressed()"), self.search)
        self.connect(self.ui.idEdit, SIGNAL("returnPressed()"), self.searchId)

        count = self.config.get('settings', 'maxresultsnumber')
        self.ui.countSpin.setValue(int(count))

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)
        self.connect(self.ui.actionQuit, SIGNAL("triggered()"), self.close)

        self.loadBackendsList()

        if self.ui.backendEdit.count() == 0:
            self.backendsConfig()

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (CapRecipe, ), self)
        if bckndcfg.run():
            self.loadBackendsList()

    def loadBackendsList(self):
        self.ui.backendEdit.clear()
        for i, backend in enumerate(self.weboob.iter_backends()):
            if i == 0:
                self.ui.backendEdit.addItem('All backends', '')
            self.ui.backendEdit.addItem(backend.name, backend.name)
            if backend.name == self.config.get('settings', 'backend'):
                self.ui.backendEdit.setCurrentIndex(i+1)

        if self.ui.backendEdit.count() == 0:
            self.ui.searchEdit.setEnabled(False)
        else:
            self.ui.searchEdit.setEnabled(True)

    def loadSearchHistory(self):
        ''' Return search string history list loaded from history file
        '''
        result = []
        history_path = os.path.join(self.weboob.workdir, 'qcookboob_history')
        if os.path.exists(history_path):
            f = codecs.open(history_path, 'r', 'utf-8')
            conf_hist = f.read()
            f.close()
            if conf_hist is not None and conf_hist.strip() != '':
                result = conf_hist.strip().split('\n')
        return result

    def saveSearchHistory(self):
        ''' Save search history in history file
        '''
        if len(self.search_history) > 0:
            history_path = os.path.join(self.weboob.workdir, 'qcookboob_history')
            f = codecs.open(history_path, 'w', 'utf-8')
            f.write('\n'.join(self.search_history))
            f.close()

    def updateCompletion(self):
        qc = QCompleter(QStringList(self.search_history), self)
        qc.setCaseSensitivity(Qt.CaseInsensitive)
        self.ui.searchEdit.setCompleter(qc)

    def getCount(self):
        num = self.ui.countSpin.value()
        if num == 0:
            return None
        else:
            return num

    def stopProcess(self):
        self.process.process.finish_event.set()

    def doAction(self, description, fun, args):
        ''' Call fun with args as arguments
        and save it in the action history
        '''
        self.ui.currentActionLabel.setText(description)
        if self.action_history['last_action'] is not None:
            self.action_history['action_list'].append(self.action_history['last_action'])
            self.ui.backButton.setToolTip(self.action_history['last_action']['description'])
            self.ui.backButton.show()
        self.action_history['last_action'] = {'function': fun, 'args': args, 'description': description}
        return fun(*args)

    def doBack(self):
        ''' Go back in action history
        Basically call previous function and update history
        '''
        if len(self.action_history['action_list']) > 0:
            todo = self.action_history['action_list'].pop()
            self.ui.currentActionLabel.setText(todo['description'])
            self.action_history['last_action'] = todo
            if len(self.action_history['action_list']) == 0:
                self.ui.backButton.hide()
            else:
                self.ui.backButton.setToolTip(self.action_history['action_list'][-1]['description'])
            return todo['function'](*todo['args'])

    def search(self):
        pattern = unicode(self.ui.searchEdit.text())
        # arbitrary max number of completion word
        if len(self.search_history) > 50:
            self.search_history.pop(0)
        if pattern not in self.search_history:
            self.search_history.append(pattern)
            self.updateCompletion()

        self.searchRecipe()

    def searchRecipe(self):
        pattern = unicode(self.ui.searchEdit.text())
        if not pattern:
            return
        self.doAction(u'Search recipe "%s"' % pattern, self.searchRecipeAction, [pattern])

    def searchRecipeAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addRecipe)
        self.process.do(self.app._do_complete, self.getCount(), ('title'), 'iter_recipes', pattern, backends=backend_name, caps=CapRecipe)
        self.ui.stopButton.show()

    def addRecipe(self, backend, recipe):
        if not backend:
            self.ui.searchEdit.setEnabled(True)
            QApplication.restoreOverrideCursor()
            self.process = None
            self.ui.stopButton.hide()
            return
        minirecipe = MiniRecipe(self.weboob, backend, recipe, self)
        self.ui.list_content.layout().addWidget(minirecipe)
        self.minis.append(minirecipe)

    def displayRecipe(self, recipe, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wrecipe = Recipe(recipe, backend, self)
        self.ui.info_content.layout().addWidget(wrecipe)
        self.current_info_widget = wrecipe
        QApplication.restoreOverrideCursor()

    def searchId(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        id = unicode(self.ui.idEdit.text())
        if '@' in id:
            backend_name = id.split('@')[1]
            id = id.split('@')[0]
        else:
            backend_name = None
        for backend in self.weboob.iter_backends():
            if (backend_name and backend.name == backend_name) or not backend_name:
                recipe = backend.get_recipe(id)
                if recipe:
                    self.doAction('Details of recipe "%s"' % recipe.title, self.displayRecipe, [recipe, backend])
        QApplication.restoreOverrideCursor()

    def closeEvent(self, ev):
        self.config.set('settings', 'backend', str(self.ui.backendEdit.itemData(
            self.ui.backendEdit.currentIndex()).toString()))
        self.saveSearchHistory()
        self.config.set('settings', 'maxresultsnumber', self.ui.countSpin.value())

        self.config.save()
        ev.accept()
Пример #16
0
class MainWindow(QtMainWindow):
    def __init__(self, config, storage, weboob, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.storage = storage
        self.weboob = weboob
        self.process = None
        self.displayed_photo_idx = 0
        self.process_photo = {}
        self.process_bookmarks = {}

        # search history is a list of patterns which have been searched
        self.search_history = self.loadSearchHistory()
        self.updateCompletion()

        self.ui.jobFrame.hide()

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"),
                     self.backendsConfig)

        self.connect(self.ui.searchEdit, SIGNAL('returnPressed()'),
                     self.doSearch)
        self.connect(
            self.ui.jobList,
            SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'),
            self.jobSelected)
        self.connect(self.ui.searchButton, SIGNAL('clicked()'), self.doSearch)

        self.connect(self.ui.refreshButton, SIGNAL('clicked()'),
                     self.doAdvancedSearch)
        self.connect(self.ui.queriesTabWidget, SIGNAL('currentChanged(int)'),
                     self.tabChange)
        self.connect(
            self.ui.jobListAdvancedSearch,
            SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'),
            self.jobSelected)

        self.connect(self.ui.idEdit, SIGNAL('returnPressed()'), self.openJob)

        if self.weboob.count_backends() == 0:
            self.backendsConfig()

    def loadSearchHistory(self):
        ''' Return search string history list loaded from history file
        '''
        result = []
        history_path = os.path.join(self.weboob.workdir, 'qhandjoob_history')
        if os.path.exists(history_path):
            f = codecs.open(history_path, 'r', 'utf-8')
            conf_hist = f.read()
            f.close()
            if conf_hist is not None and conf_hist.strip() != '':
                result = conf_hist.strip().split('\n')
        return result

    def saveSearchHistory(self):
        ''' Save search history in history file
        '''
        if len(self.search_history) > 0:
            history_path = os.path.join(self.weboob.workdir,
                                        'qhandjoob_history')
            f = codecs.open(history_path, 'w', 'utf-8')
            f.write('\n'.join(self.search_history))
            f.close()

    def updateCompletion(self):
        qc = QCompleter(QStringList(self.search_history), self)
        qc.setCaseSensitivity(Qt.CaseInsensitive)
        self.ui.searchEdit.setCompleter(qc)

    def tabChange(self, index):
        if index == 1:
            self.doAdvancedSearch()

    def doAdvancedSearch(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.ui.jobListAdvancedSearch.clear()
        self.process = QtDo(self.weboob, self.addJobAdvancedSearch)
        self.process.do('advanced_search_job')

    def doSearch(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        pattern = unicode(self.ui.searchEdit.text())

        # arbitrary max number of completion word
        if pattern:
            if len(self.search_history) > 50:
                self.search_history.pop(0)
            if pattern not in self.search_history:
                self.search_history.append(pattern)
                self.updateCompletion()

        self.ui.jobList.clear()
        self.process = QtDo(self.weboob, self.addJobSearch)
        self.process.do('search_job', pattern)

    def addJobSearch(self, backend, job):
        item = self.addJob(backend, job)
        if item:
            self.ui.jobList.addItem(item)

        if not backend:
            QApplication.restoreOverrideCursor()

    def addJobAdvancedSearch(self, backend, job):
        item = self.addJob(backend, job)
        if item:
            self.ui.jobListAdvancedSearch.addItem(item)

        if not backend:
            QApplication.restoreOverrideCursor()

    def addJob(self, backend, job):
        if not backend:
            self.process = None
            return

        if not job:
            return

        item = JobListWidgetItem(job)
        item.setAttrs(self.storage)
        return item

    def closeEvent(self, event):
        self.saveSearchHistory()
        QtMainWindow.closeEvent(self, event)

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (ICapJob, ), self)
        if bckndcfg.run():
            pass

    def jobSelected(self, item, prev):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        if item is not None:
            job = item.job
            self.ui.queriesTabWidget.setEnabled(False)

            self.process = QtDo(self.weboob, self.gotJob)
            self.process.do('fillobj', job, backends=job.backend)

        else:
            job = None

        self.setJob(job)

        if prev:
            prev.setAttrs(self.storage)

    def openJob(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        url = unicode(self.ui.idEdit.text())
        if not url:
            return

        for backend in self.weboob.iter_backends():
            job = backend.get_job_advert(url)
            if job:
                self.process = QtDo(self.weboob, self.gotJob)
                self.process.do('fillobj', job, backends=job.backend)
                break

        self.setJob(job)
        self.ui.idEdit.clear()
        QApplication.restoreOverrideCursor()

    def gotJob(self, backend, job):
        if not backend:
            self.ui.queriesTabWidget.setEnabled(True)
            self.process = None
            return

        self.setJob(job)

    def setJob(self, job):
        if job:
            self.ui.descriptionEdit.setText("%s" % job.description)
            self.ui.titleLabel.setText("<h1>%s</h1>" % job.title)
            self.ui.idLabel.setText("%s" % job.id)
            self.ui.jobNameLabel.setText("%s" % job.job_name)
            self.ui.publicationDateLabel.setText("%s" % job.publication_date)
            self.ui.societyNameLabel.setText("%s" % job.society_name)
            self.ui.placeLabel.setText("%s" % job.place)
            self.ui.payLabel.setText("%s" % job.pay)
            self.ui.contractTypeLabel.setText("%s" % job.contract_type)
            self.ui.formationLabel.setText("%s" % job.formation)
            self.ui.experienceLabel.setText("%s" % job.experience)
            self.ui.urlLabel.setText("<a href='%s'>%s</a>" %
                                     (job.url, job.url))
            self.ui.jobFrame.show()
        else:
            self.ui.jobFrame.hide()

        QApplication.restoreOverrideCursor()
Пример #17
0
class ContactProfile(QWidget):

    def __init__(self, weboob, contact, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Profile()
        self.ui.setupUi(self)

        self.connect(self.ui.previousButton, SIGNAL('clicked()'), self.previousClicked)
        self.connect(self.ui.nextButton, SIGNAL('clicked()'), self.nextClicked)

        self.weboob = weboob
        self.contact = contact
        self.loaded_profile = False
        self.displayed_photo_idx = 0
        self.process_photo = {}

        missing_fields = self.gotProfile(self.weboob.get_backend(contact.backend), contact)
        if len(missing_fields) > 0:
            self.process_contact = QtDo(self.weboob, self.gotProfile, self.gotError)
            self.process_contact.do('fillobj', self.contact, missing_fields, backends=self.contact.backend)

    def gotError(self, backend, error, backtrace):
        #self.process_contact.default_eb(backend, error, backtrace)
        self.ui.frame_photo.hide()
        self.ui.descriptionEdit.setText('<h1>Unable to show profile</h1><p>%s</p>' % error)

    def gotProfile(self, backend, contact):
        if not backend:
            return []

        missing_fields = set()

        self.display_photo()

        self.ui.nicknameLabel.setText('<h1>%s</h1>' % contact.name)
        if contact.status == Contact.STATUS_ONLINE:
            status_color = 0x00aa00
        elif contact.status == Contact.STATUS_OFFLINE:
            status_color = 0xff0000
        elif contact.status == Contact.STATUS_AWAY:
            status_color = 0xffad16
        else:
            status_color = 0xaaaaaa

        self.ui.statusLabel.setText('<font color="#%06X">%s</font>' % (status_color, contact.status_msg))
        self.ui.contactUrlLabel.setText('<b>URL:</b> <a href="%s">%s</a>' % (contact.url, contact.url))
        if contact.summary is NotLoaded:
            self.ui.descriptionEdit.setText('<h1>Description</h1><p><i>Receiving...</i></p>')
            missing_fields.add('summary')
        else:
            self.ui.descriptionEdit.setText('<h1>Description</h1><p>%s</p>' % contact.summary.replace('\n', '<br />'))

        if not contact.profile:
            missing_fields.add('profile')
        elif not self.loaded_profile:
            self.loaded_profile = True
            for head in contact.profile:
                if head.flags & head.HEAD:
                    widget = self.ui.headWidget
                else:
                    widget = self.ui.profileTab
                self.process_node(head, widget)

        return missing_fields

    def process_node(self, node, widget):
        # Set the value widget
        value = None
        if node.flags & node.SECTION:
            value = QWidget()
            value.setLayout(QFormLayout())
            for sub in node.value:
                self.process_node(sub, value)
        elif isinstance(node.value, list):
            value = QLabel('<br />'.join([unicode(s) for s in node.value]))
            value.setWordWrap(True)
        elif isinstance(node.value, tuple):
            value = QLabel(', '.join([unicode(s) for s in node.value]))
            value.setWordWrap(True)
        elif isinstance(node.value, (basestring,int,long,float)):
            value = QLabel(unicode(node.value))
        else:
            logging.warning('Not supported value: %r' % node.value)
            return

        # Insert the value widget into the parent widget, depending
        # of its type.
        if isinstance(widget, QTabWidget):
            widget.addTab(value, node.label)
        elif isinstance(widget.layout(), QFormLayout):
            label = QLabel(u'<b>%s:</b> ' % node.label)
            widget.layout().addRow(label, value)
        elif isinstance(widget.layout(), QVBoxLayout):
            widget.layout().addWidget(QLabel(u'<h3>%s</h3>' % node.label))
            widget.layout().addWidget(value)
        else:
            logging.warning('Not supported widget: %r' % widget)

    def previousClicked(self):
        self.displayed_photo_idx = (self.displayed_photo_idx - 1) % len(self.contact.photos)
        self.display_photo()

    def nextClicked(self):
        self.displayed_photo_idx = (self.displayed_photo_idx + 1) % len(self.contact.photos)
        self.display_photo()

    def display_photo(self):
        if self.displayed_photo_idx >= len(self.contact.photos):
            self.displayed_photo_idx = len(self.contact.photos) - 1
        if self.displayed_photo_idx < 0:
            self.ui.photoUrlLabel.setText('')
            return

        photo = self.contact.photos.values()[self.displayed_photo_idx]
        if photo.data:
            data = photo.data
            if photo.id in self.process_photo:
                self.process_photo.pop(photo.id)
        else:
            self.process_photo[photo.id] = QtDo(self.weboob, lambda b,p: self.display_photo())
            self.process_photo[photo.id].do('fillobj', photo, ['data'], backends=self.contact.backend)

            if photo.thumbnail_data:
                data = photo.thumbnail_data
            else:
                return

        img = QImage.fromData(data)
        img = img.scaledToWidth(self.width()/3)

        self.ui.photoLabel.setPixmap(QPixmap.fromImage(img))
        if photo.url is not NotLoaded:
            text = '<a href="%s">%s</a>' % (photo.url, photo.url)
            if photo.hidden:
                text += '<br /><font color=#ff0000><i>(Hidden photo)</i></font>'
            self.ui.photoUrlLabel.setText(text)
Пример #18
0
class EventsWidget(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Events()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.photo_processes = {}
        self.event_filter = None

        self.connect(self.ui.eventsList, SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'), self.eventDoubleClicked)
        self.connect(self.ui.typeBox, SIGNAL('currentIndexChanged(int)'), self.typeChanged)
        self.connect(self.ui.refreshButton, SIGNAL('clicked()'), self.refreshEventsList)

        self.ui.eventsList.setItemDelegate(HTMLDelegate())
        self.ui.eventsList.sortByColumn(1, Qt.DescendingOrder)

    def load(self):
        self.refreshEventsList()

    def typeChanged(self, i):
        if self.ui.refreshButton.isEnabled():
            self.refreshEventsList()

    def refreshEventsList(self):
        self.ui.eventsList.clear()
        self.ui.refreshButton.setEnabled(False)
        if self.ui.typeBox.currentIndex() >= 0:
            # XXX strangely, in gotEvent() in the loop to check if there is already the
            # event type to try to introduce it in list, itemData() returns the right value.
            # But, I don't know why, here, it will ALWAYS return None...
            # So the filter does not work currently.
            self.events_filter = self.ui.typeBox.itemData(self.ui.typeBox.currentIndex())
        else:
            self.event_filter = None
        self.ui.typeBox.setEnabled(False)
        self.ui.typeBox.clear()
        self.ui.typeBox.addItem('All', None)

        def finished():
            self.ui.refreshButton.setEnabled(True)
            self.ui.typeBox.setEnabled(True)

        self.process = QtDo(self.weboob, self.gotEvent, fb=finished)
        self.process.do('iter_events')

    def setPhoto(self, contact, item):
        if not contact:
            return False

        try:
            self.photo_processes.pop(contact.id, None)
        except KeyError:
            pass

        img = None
        for photo in contact.photos.itervalues():
            if photo.thumbnail_data:
                img = QImage.fromData(photo.thumbnail_data)
                break

        if img:
            item.setIcon(0, QIcon(QPixmap.fromImage(img)))
            self.ui.eventsList.resizeColumnToContents(0)
            return True

        return False

    def gotEvent(self, event):
        found = False
        for i in xrange(self.ui.typeBox.count()):
            s = self.ui.typeBox.itemData(i)
            if s == event.type:
                found = True
        if not found:
            print(event.type)
            self.ui.typeBox.addItem(event.type.capitalize(), event.type)
            if event.type == self.event_filter:
                self.ui.typeBox.setCurrentIndex(self.ui.typeBox.count()-1)

        if self.event_filter and self.event_filter != event.type:
            return

        if not event.contact:
            return

        contact = event.contact
        contact.backend = event.backend
        status = ''

        if contact.status == contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        name = '<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' % (contact.name, status_color, status, event.backend)
        date = event.date.strftime('%Y-%m-%d %H:%M')
        type = event.type
        message = event.message

        item = QTreeWidgetItem(None, [name, date, type, message])
        item.setData(0, Qt.UserRole, event)
        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda c: self.setPhoto(c, item))
            process.do('fillobj', contact, ['photos'], backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob, lambda p: self.setPhoto(contact, item))
                process.do('fillobj', photo, ['thumbnail_data'], backends=contact.backend)
                self.photo_processes[contact.id] = process

        self.ui.eventsList.addTopLevelItem(item)
        self.ui.eventsList.resizeColumnToContents(0)
        self.ui.eventsList.resizeColumnToContents(1)

    def eventDoubleClicked(self, item, col):
        event = item.data(0, Qt.UserRole).toPyObject()
        self.emit(SIGNAL('display_contact'), event.contact)
Пример #19
0
class MainWindow(QtMainWindow):
    def __init__(self, config, storage, weboob, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.storage = storage
        self.weboob = weboob
        self.process = None
        self.housing = None
        self.displayed_photo_idx = 0
        self.process_photo = {}
        self.process_bookmarks = {}

        self.ui.housingsList.setItemDelegate(HTMLDelegate())
        self.ui.housingFrame.hide()

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)
        self.connect(self.ui.queriesList, SIGNAL('currentIndexChanged(int)'), self.queryChanged)
        self.connect(self.ui.addQueryButton, SIGNAL('clicked()'), self.addQuery)
        self.connect(self.ui.editQueryButton, SIGNAL('clicked()'), self.editQuery)
        self.connect(self.ui.removeQueryButton, SIGNAL('clicked()'), self.removeQuery)
        self.connect(self.ui.bookmarksButton, SIGNAL('clicked()'), self.displayBookmarks)
        self.connect(self.ui.housingsList, SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'), self.housingSelected)
        self.connect(self.ui.previousButton, SIGNAL('clicked()'), self.previousClicked)
        self.connect(self.ui.nextButton, SIGNAL('clicked()'), self.nextClicked)
        self.connect(self.ui.bookmark, SIGNAL('stateChanged(int)'), self.bookmarkChanged)

        self.reloadQueriesList()
        self.refreshHousingsList()

        if self.weboob.count_backends() == 0:
            self.backendsConfig()

        if len(self.config.get('queries')) == 0:
            self.addQuery()

    def closeEvent(self, event):
        self.setHousing(None)
        QtMainWindow.closeEvent(self, event)

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (ICapHousing,), self)
        if bckndcfg.run():
            pass

    def reloadQueriesList(self, select_name=None):
        self.disconnect(self.ui.queriesList, SIGNAL('currentIndexChanged(int)'), self.queryChanged)
        self.ui.queriesList.clear()
        for name in self.config.get('queries', default={}).iterkeys():
            self.ui.queriesList.addItem(name)
            if name == select_name:
                self.ui.queriesList.setCurrentIndex(len(self.ui.queriesList)-1)
        self.connect(self.ui.queriesList, SIGNAL('currentIndexChanged(int)'), self.queryChanged)

        if select_name is not None:
            self.queryChanged()

    def removeQuery(self):
        name = unicode(self.ui.queriesList.itemText(self.ui.queriesList.currentIndex()))
        queries = self.config.get('queries')
        queries.pop(name, None)
        self.config.set('queries', queries)
        self.config.save()

        self.reloadQueriesList()
        self.queryChanged()

    def editQuery(self):
        name = unicode(self.ui.queriesList.itemText(self.ui.queriesList.currentIndex()))
        self.addQuery(name)

    def addQuery(self, name=None):
        querydlg = QueryDialog(self.weboob, self)
        if name is not None:
            query = self.config.get('queries', name)
            querydlg.ui.nameEdit.setText(name)
            querydlg.ui.nameEdit.setEnabled(False)
            for c in query['cities']:
                city = City(c['id'])
                city.backend = c['backend']
                city.name = c['name']
                item = querydlg.buildCityItem(city)
                querydlg.ui.citiesList.addItem(item)

            querydlg.ui.typeBox.setCurrentIndex(int(query.get('type', 0)))
            querydlg.ui.areaMin.setValue(query['area_min'])
            querydlg.ui.areaMax.setValue(query['area_max'])
            querydlg.ui.costMin.setValue(query['cost_min'])
            querydlg.ui.costMax.setValue(query['cost_max'])
            querydlg.selectComboValue(querydlg.ui.nbRooms, query['nb_rooms'])

        if querydlg.exec_():
            name = unicode(querydlg.ui.nameEdit.text())
            query = {}
            query['type'] = querydlg.ui.typeBox.currentIndex()
            query['cities'] = []
            for i in xrange(len(querydlg.ui.citiesList)):
                item = querydlg.ui.citiesList.item(i)
                city = item.data(Qt.UserRole).toPyObject()
                query['cities'].append({'id': city.id, 'backend': city.backend, 'name': city.name})
            query['area_min'] = querydlg.ui.areaMin.value()
            query['area_max'] = querydlg.ui.areaMax.value()
            query['cost_min'] = querydlg.ui.costMin.value()
            query['cost_max'] = querydlg.ui.costMax.value()
            try:
                query['nb_rooms'] = int(querydlg.ui.nbRooms.itemText(querydlg.ui.nbRooms.currentIndex()))
            except ValueError:
                query['nb_rooms'] = 0
            self.config.set('queries', name, query)
            self.config.save()

            self.reloadQueriesList(name)

    def queryChanged(self, i=None):
        self.refreshHousingsList()

    def refreshHousingsList(self):
        name = unicode(self.ui.queriesList.itemText(self.ui.queriesList.currentIndex()))
        q = self.config.get('queries', name)

        if q is None:
            return q

        self.ui.housingsList.clear()
        self.ui.queriesList.setEnabled(False)
        self.ui.bookmarksButton.setEnabled(False)

        query = Query()
        query.type = int(q.get('type', 0))
        query.cities = []
        for c in q['cities']:
            city = City(c['id'])
            city.backend = c['backend']
            city.name = c['name']
            query.cities.append(city)

        query.area_min = int(q['area_min']) or None
        query.area_max = int(q['area_max']) or None
        query.cost_min = int(q['cost_min']) or None
        query.cost_max = int(q['cost_max']) or None
        query.nb_rooms = int(q['nb_rooms']) or None

        self.process = QtDo(self.weboob, self.addHousing)
        self.process.do('search_housings', query)

    def displayBookmarks(self):
        self.ui.housingsList.clear()
        self.ui.queriesList.setEnabled(False)
        self.ui.queriesList.setCurrentIndex(-1)
        self.ui.bookmarksButton.setEnabled(False)

        self.processes = {}
        for id in self.storage.get('bookmarks'):
            _id, backend_name = id.rsplit('@', 1)
            self.process_bookmarks[id] = QtDo(self.weboob, self.addHousing)
            self.process_bookmarks[id].do('get_housing', _id, backends=backend_name)

    def addHousing(self, backend, housing):
        if not backend:
            self.ui.queriesList.setEnabled(True)
            self.ui.bookmarksButton.setEnabled(True)
            self.process = None
            return

        if not housing:
            return

        item = HousingListWidgetItem(housing)
        item.setAttrs(self.storage)

        if housing.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj', housing, ['photos'], backends=housing.backend)
            self.process_photo[housing.id] = process
        elif housing.photos is not NotAvailable and len(housing.photos) > 0:
            if not self.setPhoto(housing, item):
                photo = housing.photos[0]
                process = QtDo(self.weboob, lambda b, p: self.setPhoto(housing, item))
                process.do('fillobj', photo, ['data'], backends=housing.backend)
                self.process_photo[housing.id] = process

        self.ui.housingsList.addItem(item)

        if housing.fullid in self.process_bookmarks:
            self.process_bookmarks.pop(housing.fullid)

    def housingSelected(self, item, prev):
        if item is not None:
            housing = item.housing
            self.ui.queriesFrame.setEnabled(False)

            read = set(self.storage.get('read'))
            read.add(housing.fullid)
            self.storage.set('read', list(read))
            self.storage.save()

            self.process = QtDo(self.weboob, self.gotHousing)
            self.process.do('fillobj', housing, backends=housing.backend)

        else:
            housing = None

        self.setHousing(housing)

        if prev:
            prev.setAttrs(self.storage)

    def setPhoto(self, housing, item):
        if not housing:
            return False

        try:
            self.process_photo.pop(housing.id, None)
        except KeyError:
            pass

        if not housing.photos:
            return False

        img = None
        for photo in housing.photos:
            if photo.data:
                img = QImage.fromData(photo.data)
                break

        if img:
            item.setIcon(QIcon(QPixmap.fromImage(img)))
            return True

        return False

    def setHousing(self, housing, nottext='Loading...'):
        if self.housing is not None:
            self.saveNotes()

        self.housing = housing

        if self.housing is None:
            self.ui.housingFrame.hide()
            return

        self.ui.housingFrame.show()

        self.display_photo()

        self.ui.bookmark.setChecked(housing.fullid in self.storage.get('bookmarks'))

        self.ui.titleLabel.setText('<h1>%s</h1>' % housing.title)
        self.ui.areaLabel.setText(u'%s m²' % housing.area)
        self.ui.costLabel.setText(u'%s %s' % (housing.cost, housing.currency))
        self.ui.dateLabel.setText(housing.date.strftime('%Y-%m-%d') if housing.date else nottext)
        self.ui.phoneLabel.setText(housing.phone or nottext)
        self.ui.locationLabel.setText(housing.location or nottext)
        self.ui.stationLabel.setText(housing.station or nottext)

        if housing.text:
            self.ui.descriptionEdit.setText(housing.text.replace('\n', '<br/>'))
        else:
            self.ui.descriptionEdit.setText(nottext)

        self.ui.notesEdit.setText(self.storage.get('notes', housing.fullid, default=''))

        while self.ui.detailsFrame.layout().count() > 0:
            child = self.ui.detailsFrame.layout().takeAt(0)
            child.widget().hide()
            child.widget().deleteLater()

        if housing.details:
            for key, value in housing.details.iteritems():
                label = QLabel(value)
                label.setTextInteractionFlags(Qt.TextSelectableByMouse|Qt.LinksAccessibleByMouse)
                self.ui.detailsFrame.layout().addRow('<b>%s:</b>' % key, label)

    def gotHousing(self, backend, housing):
        if not backend:
            self.ui.queriesFrame.setEnabled(True)
            self.process = None
            return

        self.setHousing(housing, nottext='')

    def bookmarkChanged(self, state):
        bookmarks = set(self.storage.get('bookmarks'))
        if state == Qt.Checked:
            bookmarks.add(self.housing.fullid)
        elif self.housing.fullid in bookmarks:
            bookmarks.remove(self.housing.fullid)
        self.storage.set('bookmarks', list(bookmarks))
        self.storage.save()

    def saveNotes(self):
        if not self.housing:
            return
        txt = unicode(self.ui.notesEdit.toPlainText()).strip()
        if len(txt) > 0:
            self.storage.set('notes', self.housing.fullid, txt)
        else:
            self.storage.delete('notes', self.housing.fullid)
        self.storage.save()

    def previousClicked(self):
        if not self.housing.photos or len(self.housing.photos) == 0:
            return
        self.displayed_photo_idx = (self.displayed_photo_idx - 1) % len(self.housing.photos)
        self.display_photo()

    def nextClicked(self):
        if not self.housing.photos or len(self.housing.photos) == 0:
            return
        self.displayed_photo_idx = (self.displayed_photo_idx + 1) % len(self.housing.photos)
        self.display_photo()

    def display_photo(self):
        if not self.housing.photos:
            self.ui.photosFrame.hide()
            return

        if self.displayed_photo_idx >= len(self.housing.photos):
            self.displayed_photo_idx = len(self.housing.photos) - 1
        if self.displayed_photo_idx < 0:
            self.ui.photosFrame.hide()
            return

        self.ui.photosFrame.show()

        photo = self.housing.photos[self.displayed_photo_idx]
        if photo.data:
            data = photo.data
            if photo.id in self.process_photo:
                self.process_photo.pop(photo.id)
        else:
            self.process_photo[photo.id] = QtDo(self.weboob, lambda b,p: self.display_photo())
            self.process_photo[photo.id].do('fillobj', photo, ['data'], backends=self.housing.backend)

            return

        img = QImage.fromData(data)
        img = img.scaledToWidth(self.width()/3)

        self.ui.photoLabel.setPixmap(QPixmap.fromImage(img))
        if photo.url is not NotLoaded:
            text = '<a href="%s">%s</a>' % (photo.url, photo.url)
            self.ui.photoUrlLabel.setText(text)
Пример #20
0
class Account(QFrame):
    def __init__(self, weboob, backend, parent=None):
        QFrame.__init__(self, parent)

        self.setFrameShape(QFrame.StyledPanel)
        self.setFrameShadow(QFrame.Raised)

        self.weboob = weboob
        self.backend = backend
        self.setLayout(QVBoxLayout())
        self.timer = None

        head = QHBoxLayout()
        headw = QWidget()
        headw.setLayout(head)

        self.title = QLabel(u'<h1>%s — %s</h1>' % (backend.name, backend.DESCRIPTION))
        self.body = QLabel()

        minfo = self.weboob.repositories.get_module_info(backend.NAME)
        icon_path = self.weboob.repositories.get_module_icon_path(minfo)
        if icon_path:
            self.icon = QLabel()
            img = QImage(icon_path)
            self.icon.setPixmap(QPixmap.fromImage(img))
            head.addWidget(self.icon)

        head.addWidget(self.title)
        head.addStretch()

        self.layout().addWidget(headw)

        if backend.has_caps(CapAccount):
            self.body.setText(u'<i>Waiting...</i>')
            self.layout().addWidget(self.body)

            self.timer = self.weboob.repeat(60, self.updateStats)

    def deinit(self):
        if self.timer is not None:
            self.weboob.stop(self.timer)

    def updateStats(self):
        self.process = QtDo(self.weboob, self.updateStats_cb, self.updateStats_eb, self.updateStats_fb)
        self.process.body = u''
        self.process.in_p = False
        self.process.do('get_account_status', backends=self.backend)

    def updateStats_fb(self):
        if self.process.in_p:
            self.process.body += u"</p>"

        self.body.setText(self.process.body)

        self.process = None

    def updateStats_cb(self, field):
        if field.flags & StatusField.FIELD_HTML:
            value = u'%s' % field.value
        else:
            value = (u'%s' % field.value).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

        if field.flags & StatusField.FIELD_TEXT:
            if self.process.in_p:
                self.process.body += u'</p>'
            self.process.body += u'<p>%s</p>' % value
            self.process.in_p = False
        else:
            if not self.process.in_p:
                self.process.body += u"<p>"
                self.process.in_p = True
            else:
                self.process.body += u"<br />"

            self.process.body += u'<b>%s</b>: %s' % (field.label, field.value)

    def updateStats_eb(self, backend, err, backtrace):
        self.body.setText(u'<b>Unable to connect:</b> %s' % to_unicode(err))
        self.title.setText(u'<font color=#ff0000>%s</font>' % unicode(self.title.text()))
Пример #21
0
class ContactThread(QWidget):
    """
    The thread of the selected contact.
    """
    def __init__(self, weboob, contact, support_reply, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_ContactThread()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contact = contact
        self.thread = None
        self.messages = []
        self.process_msg = None
        self.connect(self.ui.refreshButton, SIGNAL('clicked()'),
                     self.refreshMessages)

        if support_reply:
            self.connect(self.ui.sendButton, SIGNAL('clicked()'),
                         self.postReply)
        else:
            self.ui.frame.hide()

        self.refreshMessages()

    def refreshMessages(self, fillobj=False):
        if self.process_msg:
            return

        self.ui.refreshButton.setEnabled(False)
        self.process_msg = QtDo(self.weboob, self.gotThread, self.gotError)
        if fillobj and self.thread:
            self.process_msg.do('fillobj',
                                self.thread, ['root'],
                                backends=self.contact.backend)
        else:
            self.process_msg.do('get_thread',
                                self.contact.id,
                                backends=self.contact.backend)

    def gotError(self, backend, error, backtrace):
        self.ui.textEdit.setEnabled(False)
        self.ui.sendButton.setEnabled(False)
        self.ui.refreshButton.setEnabled(True)

    def gotThread(self, backend, thread):
        if not thread:
            #v = self.ui.scrollArea.verticalScrollBar()
            #print v.minimum(), v.value(), v.maximum(), v.sliderPosition()
            #self.ui.scrollArea.verticalScrollBar().setValue(self.ui.scrollArea.verticalScrollBar().maximum())
            self.process_msg = None
            return

        self.ui.textEdit.setEnabled(True)
        self.ui.sendButton.setEnabled(True)
        self.ui.refreshButton.setEnabled(True)

        self.thread = thread

        if thread.root is NotLoaded:
            self._insert_load_button(0)
        else:
            for message in thread.iter_all_messages():
                self._insert_message(message)

    def _insert_message(self, message):
        widget = ThreadMessage(message)
        if widget in self.messages:
            old_widget = self.messages[self.messages.index(widget)]
            if old_widget.message.flags != widget.message.flags:
                old_widget.set_message(widget.message)
            return

        for i, m in enumerate(self.messages):
            if widget.message.date > m.message.date:
                self.ui.scrollAreaContent.layout().insertWidget(i, widget)
                self.messages.insert(i, widget)
                if message.parent is NotLoaded:
                    self._insert_load_button(i)
                return

        self.ui.scrollAreaContent.layout().addWidget(widget)
        self.messages.append(widget)
        if message.parent is NotLoaded:
            self._insert_load_button(-1)

    def _insert_load_button(self, pos):
        button = QPushButton(self.tr('More messages...'))
        self.connect(button, SIGNAL('clicked()'),
                     lambda: self._load_button_pressed(button))
        if pos >= 0:
            self.ui.scrollAreaContent.layout().insertWidget(pos, button)
        else:
            self.ui.scrollAreaContent.layout().addWidget(button)

    def _load_button_pressed(self, button):
        self.ui.scrollAreaContent.layout().removeWidget(button)
        button.hide()
        button.deleteLater()

        self.refreshMessages(fillobj=True)

    def postReply(self):
        text = unicode(self.ui.textEdit.toPlainText())
        self.ui.textEdit.setEnabled(False)
        self.ui.sendButton.setEnabled(False)
        m = Message(thread=self.thread,
                    id=0,
                    title=u'',
                    sender=None,
                    receivers=None,
                    content=text,
                    parent=self.messages[0].message
                    if len(self.messages) > 0 else None)
        self.process_reply = QtDo(self.weboob, self._postReply_cb,
                                  self._postReply_eb)
        self.process_reply.do('post_message', m, backends=self.contact.backend)

    def _postReply_cb(self, backend, ignored):
        if not backend:
            return
        self.ui.textEdit.clear()
        self.ui.textEdit.setEnabled(True)
        self.ui.sendButton.setEnabled(True)
        self.refreshMessages()
        self.process_reply = None

    def _postReply_eb(self, backend, error, backtrace):
        content = unicode(
            self.tr('Unable to send message:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while posting reply'),
                             content, QMessageBox.Ok)
        self.process_reply = None
Пример #22
0
class SearchWidget(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Search()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contacts = []
        self.accounts = []
        self.current = None

        self.connect(self.ui.nextButton, SIGNAL('clicked()'), self.next)
        self.connect(self.ui.queryButton, SIGNAL('clicked()'), self.sendQuery)

    def load(self):
        while self.ui.statusFrame.layout().count() > 0:
            item = self.ui.statusFrame.layout().takeAt(0)
            if item.widget():
                item.widget().deinit()
                item.widget().hide()
                item.widget().deleteLater()

        self.accounts = []

        for backend in self.weboob.iter_backends():
            account = Account(self.weboob, backend)
            account.title.setText(u'<h2>%s</h2>' % backend.name)
            self.accounts.append(account)
            self.ui.statusFrame.layout().addWidget(account)
        self.ui.statusFrame.layout().addStretch()

        self.getNewProfiles()

    def updateStats(self):
        for account in self.accounts:
            account.updateStats()

    def getNewProfiles(self):
        self.newprofiles_process = QtDo(self.weboob, self.retrieveNewContacts_cb)
        self.newprofiles_process.do('iter_new_contacts')

    def retrieveNewContacts_cb(self, backend, contact):
        if not backend:
            return

        self.contacts.insert(0, contact)
        self.ui.queueLabel.setText('%d' % len(self.contacts))
        if self.current is None:
            self.next()

    def next(self):
        try:
            contact = self.contacts.pop()
        except IndexError:
            contact = None

        self.ui.queueLabel.setText('%d' % len(self.contacts))
        self.setContact(contact)
        self.updateStats()

    def setContact(self, contact):
        self.current = contact
        if contact is not None:
            widget = ContactProfile(self.weboob, contact)
            self.ui.scrollArea.setWidget(widget)
        else:
            self.ui.scrollArea.setWidget(None)

    def sendQuery(self):
        self.newprofiles_process = QtDo(self.weboob, self.querySent)
        self.newprofiles_process.do('send_query', self.current.id, backends=[self.current.backend])

    def querySent(self, backend, query):
        if backend is None:
            self.next()
Пример #23
0
class ContactsWidget(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Contacts()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contact = None
        self.ui.contactList.setItemDelegate(HTMLDelegate())

        self.url_process = None
        self.photo_processes = {}

        self.ui.groupBox.addItem('All',
                                 MetaGroup(self.weboob, 'all', self.tr('All')))
        self.ui.groupBox.addItem(
            'Online', MetaGroup(self.weboob, 'online', self.tr('Online')))
        self.ui.groupBox.addItem(
            'Offline', MetaGroup(self.weboob, 'offline', self.tr('Offline')))
        self.ui.groupBox.setCurrentIndex(1)

        self.connect(self.ui.groupBox, SIGNAL('currentIndexChanged(int)'),
                     self.groupChanged)
        self.connect(self.ui.contactList,
                     SIGNAL('itemClicked(QListWidgetItem*)'),
                     self.contactChanged)
        self.connect(self.ui.refreshButton, SIGNAL('clicked()'),
                     self.refreshContactList)
        self.connect(self.ui.urlButton, SIGNAL('clicked()'), self.urlClicked)

    def load(self):
        self.refreshContactList()
        self.ui.backendsList.clear()
        for backend in self.weboob.iter_backends():
            self.ui.backendsList.addItem(backend.name)

    def groupChanged(self, i):
        self.refreshContactList()

    def refreshContactList(self):
        self.ui.contactList.clear()
        self.ui.refreshButton.setEnabled(False)
        i = self.ui.groupBox.currentIndex()
        group = self.ui.groupBox.itemData(i).toPyObject()
        group.iter_contacts(self.addContact)

    def setPhoto(self, contact, item):
        if not contact:
            return False

        try:
            self.photo_processes.pop(contact.id, None)
        except KeyError:
            pass

        img = None
        for photo in contact.photos.itervalues():
            if photo.thumbnail_data:
                img = QImage.fromData(photo.thumbnail_data)
                break

        if img:
            item.setIcon(QIcon(QPixmap.fromImage(img)))
            return True

        return False

    def addContact(self, contact):
        if not contact:
            self.ui.refreshButton.setEnabled(True)
            return

        status = ''
        if contact.status == Contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == Contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == Contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        item = QListWidgetItem()
        item.setText(
            '<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' %
            (contact.name, status_color, status, contact.backend))
        item.setData(Qt.UserRole, contact)

        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj',
                       contact, ['photos'],
                       backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob,
                               lambda b, p: self.setPhoto(contact, item))
                process.do('fillobj',
                           photo, ['thumbnail_data'],
                           backends=contact.backend)
                self.photo_processes[contact.id] = process

        for i in xrange(self.ui.contactList.count()):
            if self.ui.contactList.item(i).data(
                    Qt.UserRole).toPyObject().status > contact.status:
                self.ui.contactList.insertItem(i, item)
                return

        self.ui.contactList.addItem(item)

    def contactChanged(self, current):
        if not current:
            return

        contact = current.data(Qt.UserRole).toPyObject()
        self.setContact(contact)

    def setContact(self, contact):
        if not contact or contact == self.contact:
            return

        if not isinstance(contact, Contact):
            return self.retrieveContact(contact)

        self.ui.tabWidget.clear()
        self.contact = contact
        backend = self.weboob.get_backend(self.contact.backend)

        self.ui.tabWidget.addTab(ContactProfile(self.weboob, self.contact),
                                 self.tr('Profile'))
        if backend.has_caps(ICapMessages):
            self.ui.tabWidget.addTab(
                ContactThread(self.weboob, self.contact,
                              backend.has_caps(ICapMessagesPost)),
                self.tr('Messages'))
        if backend.has_caps(ICapChat):
            self.ui.tabWidget.setTabEnabled(
                self.ui.tabWidget.addTab(QWidget(), self.tr('Chat')), False)
        self.ui.tabWidget.setTabEnabled(
            self.ui.tabWidget.addTab(QWidget(), self.tr('Calendar')), False)
        self.ui.tabWidget.addTab(ContactNotes(self.weboob, self.contact),
                                 self.tr('Notes'))

    def urlClicked(self):
        url = unicode(self.ui.urlEdit.text())
        if not url:
            return

        self.retrieveContact(url)

    def retrieveContact(self, url):
        backend_name = unicode(self.ui.backendsList.currentText())
        self.ui.urlButton.setEnabled(False)
        self.url_process = QtDo(self.weboob, self.retrieveContact_cb,
                                self.retrieveContact_eb)
        self.url_process.do('get_contact', url, backends=backend_name)

    def retrieveContact_cb(self, backend, contact):
        if not backend:
            self.url_process = None
            self.ui.urlButton.setEnabled(True)
            return

        self.ui.urlEdit.clear()
        self.setContact(contact)

    def retrieveContact_eb(self, backend, error, backtrace):
        content = unicode(
            self.tr('Unable to get contact:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += u'\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while getting contact'),
                             content, QMessageBox.Ok)
Пример #24
0
class ContactProfile(QWidget):
    def __init__(self, weboob, contact, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Profile()
        self.ui.setupUi(self)

        self.connect(self.ui.previousButton, SIGNAL('clicked()'),
                     self.previousClicked)
        self.connect(self.ui.nextButton, SIGNAL('clicked()'), self.nextClicked)

        self.weboob = weboob
        self.contact = contact
        self.loaded_profile = False
        self.displayed_photo_idx = 0
        self.process_photo = {}

        missing_fields = self.gotProfile(
            self.weboob.get_backend(contact.backend), contact)
        if len(missing_fields) > 0:
            self.process_contact = QtDo(self.weboob, self.gotProfile,
                                        self.gotError)
            self.process_contact.do('fillobj',
                                    self.contact,
                                    missing_fields,
                                    backends=self.contact.backend)

    def gotError(self, backend, error, backtrace):
        self.ui.frame_photo.hide()
        self.ui.descriptionEdit.setText(
            '<h1>Unable to show profile</h1><p>%s</p>' % to_unicode(error))

    def gotProfile(self, backend, contact):
        if not backend:
            return []

        missing_fields = set()

        self.display_photo()

        self.ui.nicknameLabel.setText('<h1>%s</h1>' % contact.name)
        if contact.status == Contact.STATUS_ONLINE:
            status_color = 0x00aa00
        elif contact.status == Contact.STATUS_OFFLINE:
            status_color = 0xff0000
        elif contact.status == Contact.STATUS_AWAY:
            status_color = 0xffad16
        else:
            status_color = 0xaaaaaa

        self.ui.statusLabel.setText('<font color="#%06X">%s</font>' %
                                    (status_color, contact.status_msg))
        self.ui.contactUrlLabel.setText('<b>URL:</b> <a href="%s">%s</a>' %
                                        (contact.url, contact.url))
        if contact.summary is NotLoaded:
            self.ui.descriptionEdit.setText(
                '<h1>Description</h1><p><i>Receiving...</i></p>')
            missing_fields.add('summary')
        else:
            self.ui.descriptionEdit.setText(
                '<h1>Description</h1><p>%s</p>' %
                contact.summary.replace('\n', '<br />'))

        if not contact.profile:
            missing_fields.add('profile')
        elif not self.loaded_profile:
            self.loaded_profile = True
            for head in contact.profile.itervalues():
                if head.flags & head.HEAD:
                    widget = self.ui.headWidget
                else:
                    widget = self.ui.profileTab
                self.process_node(head, widget)

        return missing_fields

    def process_node(self, node, widget):
        # Set the value widget
        value = None
        if node.flags & node.SECTION:
            value = QWidget()
            value.setLayout(QFormLayout())
            for sub in node.value.itervalues():
                self.process_node(sub, value)
        elif isinstance(node.value, list):
            value = QLabel('<br />'.join(unicode(s) for s in node.value))
            value.setWordWrap(True)
        elif isinstance(node.value, tuple):
            value = QLabel(', '.join(unicode(s) for s in node.value))
            value.setWordWrap(True)
        elif isinstance(node.value, (basestring, int, long, float)):
            value = QLabel(unicode(node.value))
        else:
            logging.warning('Not supported value: %r' % node.value)
            return

        if isinstance(value, QLabel):
            value.setTextInteractionFlags(Qt.TextSelectableByMouse
                                          | Qt.TextSelectableByKeyboard
                                          | Qt.LinksAccessibleByMouse)

        # Insert the value widget into the parent widget, depending
        # of its type.
        if isinstance(widget, QTabWidget):
            widget.addTab(value, node.label)
        elif isinstance(widget.layout(), QFormLayout):
            label = QLabel(u'<b>%s:</b> ' % node.label)
            widget.layout().addRow(label, value)
        elif isinstance(widget.layout(), QVBoxLayout):
            widget.layout().addWidget(QLabel(u'<h3>%s</h3>' % node.label))
            widget.layout().addWidget(value)
        else:
            logging.warning('Not supported widget: %r' % widget)

    def previousClicked(self):
        if len(self.contact.photos) == 0:
            return
        self.displayed_photo_idx = (self.displayed_photo_idx - 1) % len(
            self.contact.photos)
        self.display_photo()

    def nextClicked(self):
        if len(self.contact.photos) == 0:
            return
        self.displayed_photo_idx = (self.displayed_photo_idx + 1) % len(
            self.contact.photos)
        self.display_photo()

    def display_photo(self):
        if self.displayed_photo_idx >= len(self.contact.photos):
            self.displayed_photo_idx = len(self.contact.photos) - 1
        if self.displayed_photo_idx < 0:
            self.ui.photoUrlLabel.setText('')
            return

        photo = self.contact.photos.values()[self.displayed_photo_idx]
        if photo.data:
            data = photo.data
            if photo.id in self.process_photo:
                self.process_photo.pop(photo.id)
        else:
            self.process_photo[photo.id] = QtDo(
                self.weboob, lambda b, p: self.display_photo())
            self.process_photo[photo.id].do('fillobj',
                                            photo, ['data'],
                                            backends=self.contact.backend)

            if photo.thumbnail_data:
                data = photo.thumbnail_data
            else:
                return

        img = QImage.fromData(data)
        img = img.scaledToWidth(self.width() / 3)

        self.ui.photoLabel.setPixmap(QPixmap.fromImage(img))
        if photo.url is not NotLoaded:
            text = '<a href="%s">%s</a>' % (photo.url, photo.url)
            if photo.hidden:
                text += '<br /><font color=#ff0000><i>(Hidden photo)</i></font>'
            self.ui.photoUrlLabel.setText(text)
Пример #25
0
class Result(QFrame):
    def __init__(self, weboob, app, parent=None):
        QFrame.__init__(self, parent)
        self.ui = Ui_Result()
        self.ui.setupUi(self)

        self.parent = parent
        self.weboob = weboob
        self.app = app
        self.minis = []
        self.current_info_widget = None

        # action history is composed by the last action and the action list
        # An action is a function, a list of arguments and a description string
        self.action_history = {'last_action': None, 'action_list': []}
        self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack)
        self.ui.backButton.hide()

    def doAction(self, description, fun, args):
        ''' Call fun with args as arguments
        and save it in the action history
        '''
        self.ui.currentActionLabel.setText(description)
        if self.action_history['last_action'] is not None:
            self.action_history['action_list'].append(
                self.action_history['last_action'])
            self.ui.backButton.setToolTip(
                self.action_history['last_action']['description'])
            self.ui.backButton.show()
        self.action_history['last_action'] = {
            'function': fun,
            'args': args,
            'description': description
        }
        return fun(*args)

    def doBack(self):
        ''' Go back in action history
        Basically call previous function and update history
        '''
        if len(self.action_history['action_list']) > 0:
            todo = self.action_history['action_list'].pop()
            self.ui.currentActionLabel.setText(todo['description'])
            self.action_history['last_action'] = todo
            if len(self.action_history['action_list']) == 0:
                self.ui.backButton.hide()
            else:
                self.ui.backButton.setToolTip(
                    self.action_history['action_list'][-1]['description'])
            return todo['function'](*todo['args'])

    def castingAction(self, backend_name, id, role):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.process = QtDo(self.weboob, self.addPerson)
        self.process.do('iter_movie_persons',
                        id,
                        role,
                        backends=backend_name,
                        caps=ICapCinema)
        self.parent.ui.stopButton.show()

    def filmographyAction(self, backend_name, id, role):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.process = QtDo(self.weboob, self.addMovie)
        self.process.do('iter_person_movies',
                        id,
                        role,
                        backends=backend_name,
                        caps=ICapCinema)
        self.parent.ui.stopButton.show()

    def search(self, tosearch, pattern, lang):
        if tosearch == 'person':
            self.searchPerson(pattern)
        elif tosearch == 'movie':
            self.searchMovie(pattern)
        elif tosearch == 'torrent':
            self.searchTorrent(pattern)
        elif tosearch == 'subtitle':
            self.searchSubtitle(lang, pattern)

    def searchMovie(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search movie "%s"' % pattern, self.searchMovieAction,
                      [pattern])

    def searchMovieAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addMovie)
        #self.process.do('iter_movies', pattern, backends=backend_name, caps=ICapCinema)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('original_title'),
                        'iter_movies',
                        pattern,
                        backends=backend_name,
                        caps=ICapCinema)
        self.parent.ui.stopButton.show()

    def stopProcess(self):
        self.process.process.finish_event.set()

    def addMovie(self, backend, movie):
        if not backend:
            self.parent.ui.searchEdit.setEnabled(True)
            QApplication.restoreOverrideCursor()
            self.process = None
            self.parent.ui.stopButton.hide()
            return
        minimovie = MiniMovie(self.weboob, backend, movie, self)
        self.ui.list_content.layout().addWidget(minimovie)
        self.minis.append(minimovie)

    def displayMovie(self, movie, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wmovie = Movie(movie, backend, self)
        self.ui.info_content.layout().addWidget(wmovie)
        self.current_info_widget = wmovie
        QApplication.restoreOverrideCursor()

    def searchPerson(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search person "%s"' % pattern, self.searchPersonAction,
                      [pattern])

    def searchPersonAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addPerson)
        #self.process.do('iter_persons', pattern, backends=backend_name, caps=ICapCinema)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('name'),
                        'iter_persons',
                        pattern,
                        backends=backend_name,
                        caps=ICapCinema)
        self.parent.ui.stopButton.show()

    def addPerson(self, backend, person):
        if not backend:
            self.parent.ui.searchEdit.setEnabled(True)
            QApplication.restoreOverrideCursor()
            self.process = None
            self.parent.ui.stopButton.hide()
            return
        miniperson = MiniPerson(self.weboob, backend, person, self)
        self.ui.list_content.layout().addWidget(miniperson)
        self.minis.append(miniperson)

    def displayPerson(self, person, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wperson = Person(person, backend, self)
        self.ui.info_content.layout().addWidget(wperson)
        self.current_info_widget = wperson
        QApplication.restoreOverrideCursor()

    def searchTorrent(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search torrent "%s"' % pattern,
                      self.searchTorrentAction, [pattern])

    def searchTorrentAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addTorrent)
        #self.process.do('iter_torrents', pattern, backends=backend_name, caps=ICapTorrent)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('name'),
                        'iter_torrents',
                        pattern,
                        backends=backend_name,
                        caps=ICapTorrent)
        self.parent.ui.stopButton.show()

    def addTorrent(self, backend, torrent):
        if not backend:
            self.parent.ui.searchEdit.setEnabled(True)
            QApplication.restoreOverrideCursor()
            self.process = None
            self.parent.ui.stopButton.hide()
            return
        minitorrent = MiniTorrent(self.weboob, backend, torrent, self)
        self.ui.list_content.layout().addWidget(minitorrent)
        self.minis.append(minitorrent)

    def displayTorrent(self, torrent, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wtorrent = Torrent(torrent, backend, self)
        self.ui.info_content.layout().addWidget(wtorrent)
        self.current_info_widget = wtorrent

    def searchSubtitle(self, lang, pattern):
        if not pattern:
            return
        self.doAction(u'Search subtitle "%s" (lang:%s)' % (pattern, lang),
                      self.searchSubtitleAction, [lang, pattern])

    def searchSubtitleAction(self, lang, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addSubtitle)
        #self.process.do('iter_subtitles', lang, pattern, backends=backend_name, caps=ICapSubtitle)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('name'),
                        'iter_subtitles',
                        lang,
                        pattern,
                        backends=backend_name,
                        caps=ICapSubtitle)
        self.parent.ui.stopButton.show()

    def addSubtitle(self, backend, subtitle):
        if not backend:
            self.parent.ui.searchEdit.setEnabled(True)
            QApplication.restoreOverrideCursor()
            self.process = None
            self.parent.ui.stopButton.hide()
            return
        minisubtitle = MiniSubtitle(self.weboob, backend, subtitle, self)
        self.ui.list_content.layout().addWidget(minisubtitle)
        self.minis.append(minisubtitle)

    def displaySubtitle(self, subtitle, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wsubtitle = Subtitle(subtitle, backend, self)
        self.ui.info_content.layout().addWidget(wsubtitle)
        self.current_info_widget = wsubtitle

    def searchId(self, id, stype):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        title_field = 'name'
        if stype == 'movie':
            cap = ICapCinema
            title_field = 'original_title'
        elif stype == 'person':
            cap = ICapCinema
        elif stype == 'torrent':
            cap = ICapTorrent
        elif stype == 'subtitle':
            cap = ICapSubtitle
        if '@' in id:
            backend_name = id.split('@')[1]
            id = id.split('@')[0]
        else:
            backend_name = None
        for backend in self.weboob.iter_backends():
            if backend.has_caps(cap) and (
                (backend_name and backend.name == backend_name)
                    or not backend_name):
                exec('object = backend.get_%s(id)' % (stype))
                if object:
                    func_display = 'self.display' + stype[0].upper(
                    ) + stype[1:]
                    exec(
                        "self.doAction('Details of %s \"%%s\"' %% object.%s, %s, [object, backend])"
                        % (stype, title_field, func_display))
        QApplication.restoreOverrideCursor()
Пример #26
0
class MainWindow(QtMainWindow):
    def __init__(self, config, weboob, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.weboob = weboob
        self.backend = None

        self.connect(self.ui.idEdit, SIGNAL("returnPressed()"), self.loadPage)
        self.connect(self.ui.loadButton, SIGNAL("clicked()"), self.loadPage)
        self.connect(self.ui.tabWidget, SIGNAL("currentChanged(int)"),
                     self._currentTabChanged)
        self.connect(self.ui.saveButton, SIGNAL("clicked()"), self.savePage)
        self.connect(self.ui.actionBackends, SIGNAL("triggered()"),
                     self.backendsConfig)
        self.connect(self.ui.contentEdit, SIGNAL("textChanged()"),
                     self._textChanged)
        self.connect(self.ui.loadHistoryButton, SIGNAL("clicked()"),
                     self.loadHistory)

        if hasattr(self.ui.descriptionEdit, "setPlaceholderText"):
            self.ui.descriptionEdit.setPlaceholderText("Edit summary")

        if self.weboob.count_backends() == 0:
            self.backendsConfig()
        else:
            self.loadBackends()

    def backendsConfig(self):
        """ Opens backends configuration dialog when 'Backends' is clicked """
        bckndcfg = BackendCfg(self.weboob, (ICapContent, ), self)
        if bckndcfg.run():
            self.loadBackends()

    def loadBackends(self):
        """ Fills the backends comboBox with available backends """
        self.ui.backendBox.clear()
        for backend in self.weboob.iter_backends():
            self.ui.backendBox.insertItem(0, backend.name)

    def _currentTabChanged(self):
        """ Loads history or preview when the corresponding tabs are shown """
        if self.ui.tabWidget.currentIndex() == 1:
            if self.backend is not None:
                self.loadPreview()
        elif self.ui.tabWidget.currentIndex() == 2:
            if self.backend is not None:
                self.loadHistory()

    def _textChanged(self):
        """ The text in the content QPlainTextEdit has changed """
        if self.backend:
            self.ui.saveButton.setEnabled(True)
            self.ui.saveButton.setText('Save')

    def loadPage(self):
        """ Loads a page's source into the 'content' QPlainTextEdit """
        _id = unicode(self.ui.idEdit.text())
        if not _id:
            return

        self.ui.loadButton.setEnabled(False)
        self.ui.loadButton.setText('Loading...')
        self.ui.contentEdit.setReadOnly(True)

        backend = str(self.ui.backendBox.currentText())
        self.process = QtDo(self.weboob, self._loadedPage, self._errorLoadPage)
        self.process.do('get_content', _id, backends=(backend, ))

    def _loadedPage(self, backend, data):
        """ Callback for loadPage """
        if not backend:
            # Loading is finished
            self.process = None
            if self.backend:
                self.ui.contentEdit.setReadOnly(False)
                self.ui.loadButton.setEnabled(True)
                self.ui.loadButton.setText('Load')
            return
        if not data:
            self.content = None
            self.backend = None
            QMessageBox.critical(
                self, self.tr('Unable to open page'),
                'Unable to open page "%s" on %s: it does not exist.' %
                (self.ui.idEdit.text(), self.ui.backendBox.currentText()),
                QMessageBox.Ok)
            return

        self.content = data
        self.ui.contentEdit.setPlainText(self.content.content)
        self.setWindowTitle("QWebcontentedit - %s@%s" %
                            (self.content.id, backend.name))
        self.backend = backend

    def _errorLoadPage(self, backend, error, backtrace):
        """ Error callback for loadPage """
        content = unicode(
            self.tr('Unable to load page:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while loading page'),
                             content, QMessageBox.Ok)
        self.ui.loadButton.setEnabled(True)
        self.ui.loadButton.setText("Load")

    def savePage(self):
        """ Saves the current page to the remote site """
        if self.backend is None:
            return
        new_content = unicode(self.ui.contentEdit.toPlainText())
        minor = self.ui.minorBox.isChecked()
        if new_content != self.content.content:
            self.ui.saveButton.setEnabled(False)
            self.ui.saveButton.setText('Saving...')
            self.ui.contentEdit.setReadOnly(True)
            self.content.content = new_content
            message = unicode(self.ui.descriptionEdit.text())
            self.process = QtDo(self.weboob, self._savedPage,
                                self._errorSavePage)
            self.process.do('push_content',
                            self.content,
                            message,
                            minor=minor,
                            backends=self.backend)

    def _savedPage(self, backend, data):
        """ Callback for savePage's QtDo """
        if not backend:
            # saving has finished
            self.process = None
            self.ui.saveButton.setText('Saved')
            self.ui.contentEdit.setReadOnly(False)
            return
        self.ui.descriptionEdit.clear()

    def _errorSavePage(self, backend, error, backtrace):
        """ """
        content = unicode(
            self.tr('Unable to save page:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while saving page'), content,
                             QMessageBox.Ok)
        self.ui.saveButton.setEnabled(True)
        self.ui.saveButton.setText("Save")

    def loadPreview(self):
        """ Loads the current page's preview into the preview QTextEdit """
        tmp_content = deepcopy(self.content)
        tmp_content.content = unicode(self.ui.contentEdit.toPlainText())
        self.ui.previewEdit.setHtml(
            self.backend.get_content_preview(tmp_content))

    def loadHistory(self):
        """ Loads the page's log into the 'History' tab """
        if self.backend is None:
            return

        self.ui.loadHistoryButton.setEnabled(False)
        self.ui.loadHistoryButton.setText("Loading...")

        self.ui.historyTable.clear()
        self.ui.historyTable.setRowCount(0)

        self.ui.historyTable.setHorizontalHeaderLabels(
            ["Revision", "Time", "Author", "Summary"])
        self.ui.historyTable.setColumnWidth(3, 1000)

        self.process = QtDo(self.weboob, self._gotRevision, self._errorHistory)
        self.process.do('iter_revisions',
                        self.content.id,
                        max_results=self.ui.nbRevBox.value(),
                        backends=(self.backend, ))

    def _gotRevision(self, backend, revision):
        """ Callback for loadHistory's QtDo """
        if not backend:
            # The last revision has been processed
            self.process = None
            self.ui.loadHistoryButton.setEnabled(True)
            self.ui.loadHistoryButton.setText("Reload")
            return

        # we set the flags to Qt.ItemIsEnabled so that the items
        # are not modifiable (they are modifiable by default)
        item_revision = QTableWidgetItem(revision.id)
        item_revision.setFlags(Qt.ItemIsEnabled)

        item_time = QTableWidgetItem(
            revision.timestamp.strftime('%Y-%m-%d %H:%M:%S'))
        item_time.setFlags(Qt.ItemIsEnabled)

        item_author = QTableWidgetItem(revision.author)
        item_author.setFlags(Qt.ItemIsEnabled)

        item_summary = QTableWidgetItem(revision.comment)
        item_summary.setFlags(Qt.ItemIsEnabled)

        row = self.ui.historyTable.currentRow() + 1
        self.ui.historyTable.insertRow(row)
        self.ui.historyTable.setItem(row, 0, item_revision)
        self.ui.historyTable.setItem(row, 1, item_time)
        self.ui.historyTable.setItem(row, 2, item_author)
        self.ui.historyTable.setItem(row, 3, item_summary)

        self.ui.historyTable.setCurrentCell(row, 0)

    def _errorHistory(self, backend, error, backtrace):
        """ Loading the history has failed """
        content = unicode(
            self.tr('Unable to load history:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while loading history'),
                             content, QMessageBox.Ok)

        self.ui.loadHistoryButton.setEnabled(True)
        self.ui.loadHistoryButton.setText("Reload")
Пример #27
0
class Result(QFrame):
    def __init__(self, weboob, app, parent=None):
        QFrame.__init__(self, parent)
        self.ui = Ui_Result()
        self.ui.setupUi(self)

        self.parent = parent
        self.weboob = weboob
        self.app = app
        self.minis = []
        self.current_info_widget = None

        # action history is composed by the last action and the action list
        # An action is a function, a list of arguments and a description string
        self.action_history = {'last_action': None, 'action_list': []}
        self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack)
        self.ui.backButton.hide()

    def doAction(self, description, fun, args):
        ''' Call fun with args as arguments
        and save it in the action history
        '''
        self.ui.currentActionLabel.setText(description)
        if self.action_history['last_action'] is not None:
            self.action_history['action_list'].append(
                self.action_history['last_action'])
            self.ui.backButton.setToolTip(
                self.action_history['last_action']['description'])
            self.ui.backButton.show()
        self.action_history['last_action'] = {
            'function': fun,
            'args': args,
            'description': description
        }
        return fun(*args)

    def doBack(self):
        ''' Go back in action history
        Basically call previous function and update history
        '''
        if len(self.action_history['action_list']) > 0:
            todo = self.action_history['action_list'].pop()
            self.ui.currentActionLabel.setText(todo['description'])
            self.action_history['last_action'] = todo
            if len(self.action_history['action_list']) == 0:
                self.ui.backButton.hide()
            else:
                self.ui.backButton.setToolTip(
                    self.action_history['action_list'][-1]['description'])
            return todo['function'](*todo['args'])

    def processFinished(self):
        self.parent.ui.searchEdit.setEnabled(True)
        QApplication.restoreOverrideCursor()
        self.process = None
        self.parent.ui.stopButton.hide()

    def searchRecipe(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search recipe "%s"' % pattern, self.searchRecipeAction,
                      [pattern])

    def searchRecipeAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob,
                            self.addRecipe,
                            fb=self.processFinished)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('title'),
                        'iter_recipes',
                        pattern,
                        backends=backend_name,
                        caps=CapRecipe)
        self.parent.ui.stopButton.show()

    def addRecipe(self, recipe):
        minirecipe = MiniRecipe(self.weboob, self.weboob[recipe.backend],
                                recipe, self)
        self.ui.list_content.layout().insertWidget(
            self.ui.list_content.layout().count() - 1, minirecipe)
        self.minis.append(minirecipe)

    def displayRecipe(self, recipe, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wrecipe = Recipe(recipe, backend, self)
        self.ui.info_content.layout().addWidget(wrecipe)
        self.current_info_widget = wrecipe
        QApplication.restoreOverrideCursor()

    def searchId(self, id):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        if '@' in id:
            backend_name = id.split('@')[1]
            id = id.split('@')[0]
        else:
            backend_name = None
        for backend in self.weboob.iter_backends():
            if (backend_name
                    and backend.name == backend_name) or not backend_name:
                recipe = backend.get_recipe(id)
                if recipe:
                    self.doAction('Details of recipe "%s"' % recipe.title,
                                  self.displayRecipe, [recipe, backend])
        QApplication.restoreOverrideCursor()
Пример #28
0
class Result(QFrame):
    def __init__(self, weboob, app, parent=None):
        QFrame.__init__(self, parent)
        self.ui = Ui_Result()
        self.ui.setupUi(self)

        self.parent = parent
        self.weboob = weboob
        self.app = app
        self.minis = []
        self.current_info_widget = None

        # action history is composed by the last action and the action list
        # An action is a function, a list of arguments and a description string
        self.action_history = {'last_action': None, 'action_list': []}
        self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack)
        self.ui.backButton.hide()

    def doAction(self, description, fun, args):
        ''' Call fun with args as arguments
        and save it in the action history
        '''
        self.ui.currentActionLabel.setText(description)
        if self.action_history['last_action'] is not None:
            self.action_history['action_list'].append(self.action_history['last_action'])
            self.ui.backButton.setToolTip(self.action_history['last_action']['description'])
            self.ui.backButton.show()
        self.action_history['last_action'] = {'function': fun, 'args': args, 'description': description}
        return fun(*args)

    def doBack(self):
        ''' Go back in action history
        Basically call previous function and update history
        '''
        if len(self.action_history['action_list']) > 0:
            todo = self.action_history['action_list'].pop()
            self.ui.currentActionLabel.setText(todo['description'])
            self.action_history['last_action'] = todo
            if len(self.action_history['action_list']) == 0:
                self.ui.backButton.hide()
            else:
                self.ui.backButton.setToolTip(self.action_history['action_list'][-1]['description'])
            return todo['function'](*todo['args'])

    def processFinished(self):
        self.parent.ui.searchEdit.setEnabled(True)
        QApplication.restoreOverrideCursor()
        self.process = None
        self.parent.ui.stopButton.hide()

    def searchRecipe(self,pattern):
        if not pattern:
            return
        self.doAction(u'Search recipe "%s"' % pattern, self.searchRecipeAction, [pattern])

    def searchRecipeAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addRecipe, fb=self.processFinished)
        self.process.do(self.app._do_complete, self.parent.getCount(), ('title'), 'iter_recipes', pattern, backends=backend_name, caps=CapRecipe)
        self.parent.ui.stopButton.show()

    def addRecipe(self, recipe):
        minirecipe = MiniRecipe(self.weboob, self.weboob[recipe.backend], recipe, self)
        self.ui.list_content.layout().insertWidget(self.ui.list_content.layout().count()-1,minirecipe)
        self.minis.append(minirecipe)

    def displayRecipe(self, recipe, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wrecipe = Recipe(recipe, backend, self)
        self.ui.info_content.layout().addWidget(wrecipe)
        self.current_info_widget = wrecipe
        QApplication.restoreOverrideCursor()

    def searchId(self, id):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        if '@' in id:
            backend_name = id.split('@')[1]
            id = id.split('@')[0]
        else:
            backend_name = None
        for backend in self.weboob.iter_backends():
            if (backend_name and backend.name == backend_name) or not backend_name:
                recipe = backend.get_recipe(id)
                if recipe:
                    self.doAction('Details of recipe "%s"' % recipe.title, self.displayRecipe, [recipe, backend])
        QApplication.restoreOverrideCursor()
Пример #29
0
class MainWindow(QtMainWindow):
    def __init__(self, config, weboob, app, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.weboob = weboob
        self.minivideos = []
        self.app = app

        self.ui.sortbyEdit.setCurrentIndex(int(self.config.get('settings', 'sortby')))
        self.ui.nsfwCheckBox.setChecked(int(self.config.get('settings', 'nsfw')))
        self.ui.sfwCheckBox.setChecked(int(self.config.get('settings', 'sfw')))

        self.connect(self.ui.searchEdit, SIGNAL("returnPressed()"), self.search)
        self.connect(self.ui.urlEdit, SIGNAL("returnPressed()"), self.openURL)
        self.connect(self.ui.nsfwCheckBox, SIGNAL("stateChanged(int)"), self.nsfwChanged)
        self.connect(self.ui.sfwCheckBox, SIGNAL("stateChanged(int)"), self.sfwChanged)

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)

        self.loadBackendsList()

        if self.ui.backendEdit.count() == 0:
            self.backendsConfig()

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (CapVideo,), self)
        if bckndcfg.run():
            self.loadBackendsList()

    def loadBackendsList(self):
        self.ui.backendEdit.clear()
        for i, backend in enumerate(self.weboob.iter_backends()):
            if i == 0:
                self.ui.backendEdit.addItem('All backends', '')
            self.ui.backendEdit.addItem(backend.name, backend.name)
            if backend.name == self.config.get('settings', 'backend'):
                self.ui.backendEdit.setCurrentIndex(i+1)

        if self.ui.backendEdit.count() == 0:
            self.ui.searchEdit.setEnabled(False)
            self.ui.urlEdit.setEnabled(False)
        else:
            self.ui.searchEdit.setEnabled(True)
            self.ui.urlEdit.setEnabled(True)

    def nsfwChanged(self, state):
        self.config.set('settings', 'nsfw', int(self.ui.nsfwCheckBox.isChecked()))
        self.updateVideosDisplay()

    def sfwChanged(self, state):
        self.config.set('settings', 'sfw', int(self.ui.sfwCheckBox.isChecked()))
        self.updateVideosDisplay()

    def updateVideosDisplay(self):
        for minivideo in self.minivideos:
            if (minivideo.video.nsfw and self.ui.nsfwCheckBox.isChecked() or
                    not minivideo.video.nsfw and self.ui.sfwCheckBox.isChecked()):
                minivideo.show()
            else:
                minivideo.hide()

    def search(self):
        pattern = unicode(self.ui.searchEdit.text())
        if not pattern:
            return

        for minivideo in self.minivideos:
            self.ui.scrollAreaContent.layout().removeWidget(minivideo)
            minivideo.hide()
            minivideo.deleteLater()

        self.minivideos = []
        self.ui.searchEdit.setEnabled(False)

        backend_name = str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString())

        def finished():
            self.ui.searchEdit.setEnabled(True)
            self.process = None

        self.process = QtDo(self.weboob, self.addVideo, fb=finished)
        self.process.do(self.app._do_complete, 20, (), 'search_videos', pattern, self.ui.sortbyEdit.currentIndex(), nsfw=True, backends=backend_name)

    def addVideo(self, video):
        minivideo = MiniVideo(self.weboob, self.weboob[video.backend], video)
        self.ui.scrollAreaContent.layout().addWidget(minivideo)
        self.minivideos.append(minivideo)
        if (video.nsfw and not self.ui.nsfwCheckBox.isChecked() or
                not video.nsfw and not self.ui.sfwCheckBox.isChecked()):
            minivideo.hide()

    def openURL(self):
        url = unicode(self.ui.urlEdit.text())
        if not url:
            return

        for backend in self.weboob.iter_backends():
            video = backend.get_video(url)
            if video:
                video_widget = Video(video, self)
                video_widget.show()

        self.ui.urlEdit.clear()

    def closeEvent(self, ev):
        self.config.set('settings', 'backend', str(self.ui.backendEdit.itemData(self.ui.backendEdit.currentIndex()).toString()))
        self.config.set('settings', 'sortby', self.ui.sortbyEdit.currentIndex())
        self.config.save()
        ev.accept()
Пример #30
0
class ContactsWidget(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Contacts()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contact = None
        self.ui.contactList.setItemDelegate(HTMLDelegate())

        self.url_process = None
        self.photo_processes = {}

        self.ui.groupBox.addItem('All', MetaGroup(self.weboob, 'all', self.tr('All')))
        self.ui.groupBox.addItem('Onlines', MetaGroup(self.weboob, 'online', self.tr('Online')))
        self.ui.groupBox.addItem('Offlines', MetaGroup(self.weboob, 'offline', self.tr('Offline')))
        self.ui.groupBox.setCurrentIndex(1)

        self.connect(self.ui.groupBox, SIGNAL('currentIndexChanged(int)'), self.groupChanged)
        self.connect(self.ui.contactList, SIGNAL('itemClicked(QListWidgetItem*)'), self.contactChanged)
        self.connect(self.ui.refreshButton, SIGNAL('clicked()'), self.refreshContactList)
        self.connect(self.ui.urlButton, SIGNAL('clicked()'), self.urlClicked)

    def load(self):
        self.refreshContactList()
        self.ui.backendsList.clear()
        for backend in self.weboob.iter_backends():
            self.ui.backendsList.addItem(backend.name)

    def groupChanged(self, i):
        self.refreshContactList()

    def refreshContactList(self):
        self.ui.contactList.clear()
        self.ui.refreshButton.setEnabled(False)
        i = self.ui.groupBox.currentIndex()
        group = self.ui.groupBox.itemData(i).toPyObject()
        group.iter_contacts(self.addContact)

    def setPhoto(self, contact, item):
        if not contact:
            return False

        try:
            self.photo_processes.pop(contact.id, None)
        except KeyError:
            pass

        img = None
        for photo in contact.photos.itervalues():
            if photo.thumbnail_data:
                img = QImage.fromData(photo.thumbnail_data)
                break

        if img:
            item.setIcon(QIcon(QPixmap.fromImage(img)))
            return True

        return False

    def addContact(self, contact):
        if not contact:
            self.ui.refreshButton.setEnabled(True)
            return

        status = ''
        if contact.status == Contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == Contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == Contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        item = QListWidgetItem()
        item.setText('<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' % (contact.name, status_color, status, contact.backend))
        item.setData(Qt.UserRole, contact)

        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj', contact, ['photos'], backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob, lambda b, p: self.setPhoto(contact, item))
                process.do('fillobj', photo, ['thumbnail_data'], backends=contact.backend)
                self.photo_processes[contact.id] = process

        for i in xrange(self.ui.contactList.count()):
            if self.ui.contactList.item(i).data(Qt.UserRole).toPyObject().status > contact.status:
                self.ui.contactList.insertItem(i, item)
                return

        self.ui.contactList.addItem(item)

    def contactChanged(self, current):
        if not current:
            return

        contact = current.data(Qt.UserRole).toPyObject()
        self.setContact(contact)

    def setContact(self, contact):
        if not contact or contact == self.contact:
            return

        self.ui.tabWidget.clear()
        self.contact = contact
        backend = self.weboob.get_backend(self.contact.backend)

        self.ui.tabWidget.addTab(ContactProfile(self.weboob, self.contact), self.tr('Profile'))
        if backend.has_caps(ICapMessages):
            self.ui.tabWidget.addTab(ContactThread(self.weboob, self.contact, backend.has_caps(ICapMessagesPost)), self.tr('Messages'))
        if backend.has_caps(ICapChat):
            self.ui.tabWidget.addTab(QWidget(), self.tr('Chat'))
        self.ui.tabWidget.addTab(QWidget(), self.tr('Calendar'))
        self.ui.tabWidget.addTab(QWidget(), self.tr('Notes'))

    def urlClicked(self):
        url = unicode(self.ui.urlEdit.text())
        if not url:
            return

        backend_name = unicode(self.ui.backendsList.currentText())
        self.ui.urlButton.setEnabled(False)
        self.url_process = QtDo(self.weboob, self.urlClicked_cb, self.urlClicked_eb)
        self.url_process.do('get_contact', url, backends=backend_name)

    def urlClicked_cb(self, backend, contact):
        if not backend:
            self.url_process = None
            self.ui.urlButton.setEnabled(True)
            return

        self.ui.urlEdit.clear()
        self.setContact(contact)

    def urlClicked_eb(self, backend, error, backtrace):
        content = unicode(self.tr('Unable to get contact:\n%s\n')) % error
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % backtrace
        QMessageBox.critical(self, self.tr('Error while getting contact'),
                             content, QMessageBox.Ok)
Пример #31
0
class Result(QFrame):
    def __init__(self, weboob, app, parent=None):
        QFrame.__init__(self, parent)
        self.ui = Ui_Result()
        self.ui.setupUi(self)

        self.parent = parent
        self.weboob = weboob
        self.app = app
        self.minis = []
        self.current_info_widget = None

        # action history is composed by the last action and the action list
        # An action is a function, a list of arguments and a description string
        self.action_history = {'last_action': None, 'action_list': []}
        self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack)
        self.ui.backButton.hide()

    def doAction(self, description, fun, args):
        ''' Call fun with args as arguments
        and save it in the action history
        '''
        self.ui.currentActionLabel.setText(description)
        if self.action_history['last_action'] is not None:
            self.action_history['action_list'].append(
                self.action_history['last_action'])
            self.ui.backButton.setToolTip(
                self.action_history['last_action']['description'])
            self.ui.backButton.show()
        self.action_history['last_action'] = {
            'function': fun,
            'args': args,
            'description': description
        }
        return fun(*args)

    def doBack(self):
        ''' Go back in action history
        Basically call previous function and update history
        '''
        if len(self.action_history['action_list']) > 0:
            todo = self.action_history['action_list'].pop()
            self.ui.currentActionLabel.setText(todo['description'])
            self.action_history['last_action'] = todo
            if len(self.action_history['action_list']) == 0:
                self.ui.backButton.hide()
            else:
                self.ui.backButton.setToolTip(
                    self.action_history['action_list'][-1]['description'])
            return todo['function'](*todo['args'])

    def castingAction(self, backend_name, id, role):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.process = QtDo(self.weboob,
                            self.addPerson,
                            fb=self.processFinished)
        self.process.do('iter_movie_persons',
                        id,
                        role,
                        backends=backend_name,
                        caps=CapCinema)
        self.parent.ui.stopButton.show()

    def moviesInCommonAction(self, backend_name, id1, id2):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        for a_backend in self.weboob.iter_backends():
            if (backend_name and a_backend.name == backend_name):
                backend = a_backend
                person1 = backend.get_person(id1)
                person2 = backend.get_person(id2)

        lid1 = []
        for p in backend.iter_person_movies_ids(id1):
            lid1.append(p)
        lid2 = []
        for p in backend.iter_person_movies_ids(id2):
            lid2.append(p)

        inter = list(set(lid1) & set(lid2))

        chrono_list = []
        for common in inter:
            movie = backend.get_movie(common)
            movie.backend = backend_name
            role1 = movie.get_roles_by_person_id(person1.id)
            role2 = movie.get_roles_by_person_id(person2.id)
            if (movie.release_date != NotAvailable):
                year = movie.release_date.year
            else:
                year = '????'
            movie.short_description = '(%s) %s as %s ; %s as %s' % (
                year, person1.name, ', '.join(role1), person2.name,
                ', '.join(role2))
            i = 0
            while (i < len(chrono_list) and movie.release_date != NotAvailable
                   and (chrono_list[i].release_date == NotAvailable
                        or year > chrono_list[i].release_date.year)):
                i += 1
            chrono_list.insert(i, movie)

        for movie in chrono_list:
            self.addMovie(movie)

        self.processFinished()

    def personsInCommonAction(self, backend_name, id1, id2):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        for a_backend in self.weboob.iter_backends():
            if (backend_name and a_backend.name == backend_name):
                backend = a_backend
                movie1 = backend.get_movie(id1)
                movie2 = backend.get_movie(id2)

        lid1 = []
        for p in backend.iter_movie_persons_ids(id1):
            lid1.append(p)
        lid2 = []
        for p in backend.iter_movie_persons_ids(id2):
            lid2.append(p)

        inter = list(set(lid1) & set(lid2))

        for common in inter:
            person = backend.get_person(common)
            person.backend = backend_name
            role1 = movie1.get_roles_by_person_id(person.id)
            role2 = movie2.get_roles_by_person_id(person.id)
            person.short_description = '%s in %s ; %s in %s' % (
                ', '.join(role1), movie1.original_title, ', '.join(role2),
                movie2.original_title)
            self.addPerson(person)

        self.processFinished()

    def filmographyAction(self, backend_name, id, role):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.process = QtDo(self.weboob,
                            self.addMovie,
                            fb=self.processFinished)
        self.process.do('iter_person_movies',
                        id,
                        role,
                        backends=backend_name,
                        caps=CapCinema)
        self.parent.ui.stopButton.show()

    def search(self, tosearch, pattern, lang):
        if tosearch == 'person':
            self.searchPerson(pattern)
        elif tosearch == 'movie':
            self.searchMovie(pattern)
        elif tosearch == 'torrent':
            self.searchTorrent(pattern)
        elif tosearch == 'subtitle':
            self.searchSubtitle(lang, pattern)

    def searchMovie(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search movie "%s"' % pattern, self.searchMovieAction,
                      [pattern])

    def searchMovieAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob,
                            self.addMovie,
                            fb=self.processFinished)
        #self.process.do('iter_movies', pattern, backends=backend_name, caps=CapCinema)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('original_title'),
                        'iter_movies',
                        pattern,
                        backends=backend_name,
                        caps=CapCinema)
        self.parent.ui.stopButton.show()

    def stopProcess(self):
        self.process.process.finish_event.set()

    def addMovie(self, movie):
        minimovie = MiniMovie(self.weboob, self.weboob[movie.backend], movie,
                              self)
        self.ui.list_content.layout().insertWidget(
            self.ui.list_content.layout().count() - 1, minimovie)
        self.minis.append(minimovie)

    def displayMovie(self, movie, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wmovie = Movie(movie, backend, self)
        self.ui.info_content.layout().addWidget(wmovie)
        self.current_info_widget = wmovie
        QApplication.restoreOverrideCursor()

    def searchPerson(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search person "%s"' % pattern, self.searchPersonAction,
                      [pattern])

    def searchPersonAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob,
                            self.addPerson,
                            fb=self.processFinished)
        #self.process.do('iter_persons', pattern, backends=backend_name, caps=CapCinema)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('name'),
                        'iter_persons',
                        pattern,
                        backends=backend_name,
                        caps=CapCinema)
        self.parent.ui.stopButton.show()

    def addPerson(self, person):
        miniperson = MiniPerson(self.weboob, self.weboob[person.backend],
                                person, self)
        self.ui.list_content.layout().insertWidget(
            self.ui.list_content.layout().count() - 1, miniperson)
        self.minis.append(miniperson)

    def displayPerson(self, person, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wperson = Person(person, backend, self)
        self.ui.info_content.layout().addWidget(wperson)
        self.current_info_widget = wperson
        QApplication.restoreOverrideCursor()

    def searchTorrent(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search torrent "%s"' % pattern,
                      self.searchTorrentAction, [pattern])

    def searchTorrentAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob,
                            self.addTorrent,
                            fb=self.processFinished)
        #self.process.do('iter_torrents', pattern, backends=backend_name, caps=CapTorrent)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('name'),
                        'iter_torrents',
                        pattern,
                        backends=backend_name,
                        caps=CapTorrent)
        self.parent.ui.stopButton.show()

    def processFinished(self):
        self.parent.ui.searchEdit.setEnabled(True)
        QApplication.restoreOverrideCursor()
        self.process = None
        self.parent.ui.stopButton.hide()

    def addTorrent(self, torrent):
        minitorrent = MiniTorrent(self.weboob, self.weboob[torrent.backend],
                                  torrent, self)
        self.ui.list_content.layout().insertWidget(
            self.ui.list_content.layout().count() - 1, minitorrent)
        self.minis.append(minitorrent)

    def displayTorrent(self, torrent, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wtorrent = Torrent(torrent, backend, self)
        self.ui.info_content.layout().addWidget(wtorrent)
        self.current_info_widget = wtorrent

    def searchSubtitle(self, lang, pattern):
        if not pattern:
            return
        self.doAction(u'Search subtitle "%s" (lang:%s)' % (pattern, lang),
                      self.searchSubtitleAction, [lang, pattern])

    def searchSubtitleAction(self, lang, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.parent.ui.backendEdit.itemData(
                self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob,
                            self.addSubtitle,
                            fb=self.processFinished)
        #self.process.do('iter_subtitles', lang, pattern, backends=backend_name, caps=CapSubtitle)
        self.process.do(self.app._do_complete,
                        self.parent.getCount(), ('name'),
                        'iter_subtitles',
                        lang,
                        pattern,
                        backends=backend_name,
                        caps=CapSubtitle)
        self.parent.ui.stopButton.show()

    def addSubtitle(self, subtitle):
        minisubtitle = MiniSubtitle(self.weboob, self.weboob[subtitle.backend],
                                    subtitle, self)
        self.ui.list_content.layout().insertWidget(
            self.ui.list_content.layout().count() - 1, minisubtitle)
        self.minis.append(minisubtitle)

    def displaySubtitle(self, subtitle, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wsubtitle = Subtitle(subtitle, backend, self)
        self.ui.info_content.layout().addWidget(wsubtitle)
        self.current_info_widget = wsubtitle

    def searchId(self, id, stype):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        title_field = 'name'
        if stype == 'movie':
            cap = CapCinema
            title_field = 'original_title'
        elif stype == 'person':
            cap = CapCinema
        elif stype == 'torrent':
            cap = CapTorrent
        elif stype == 'subtitle':
            cap = CapSubtitle
        if '@' in id:
            backend_name = id.split('@')[1]
            id = id.split('@')[0]
        else:
            backend_name = None
        for backend in self.weboob.iter_backends():
            if backend.has_caps(cap) and (
                (backend_name and backend.name == backend_name)
                    or not backend_name):
                exec('object = backend.get_%s(id)' % (stype))
                if object:
                    func_display = 'self.display' + stype[0].upper(
                    ) + stype[1:]
                    exec(
                        "self.doAction('Details of %s \"%%s\"' %% object.%s, %s, [object, backend])"
                        % (stype, title_field, func_display))
        QApplication.restoreOverrideCursor()
Пример #32
0
class ContactThread(QWidget):
    """
    The thread of the selected contact.
    """

    def __init__(self, weboob, contact, support_reply, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_ContactThread()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contact = contact
        self.thread = None
        self.messages = []
        self.process_msg = None
        self.connect(self.ui.refreshButton, SIGNAL('clicked()'), self.refreshMessages)

        if support_reply:
            self.connect(self.ui.sendButton, SIGNAL('clicked()'), self.postReply)
        else:
            self.ui.frame.hide()

        self.refreshMessages()

    def refreshMessages(self, fillobj=False):
        if self.process_msg:
            return

        self.ui.refreshButton.setEnabled(False)
        self.process_msg = QtDo(self.weboob, self.gotThread, self.gotError)
        if fillobj and self.thread:
            self.process_msg.do('fillobj', self.thread, ['root'], backends=self.contact.backend)
        else:
            self.process_msg.do('get_thread', self.contact.id, backends=self.contact.backend)

    def gotError(self, backend, error, backtrace):
        self.ui.textEdit.setEnabled(False)
        self.ui.sendButton.setEnabled(False)
        self.ui.refreshButton.setEnabled(True)

    def gotThread(self, backend, thread):
        if not thread:
            #v = self.ui.scrollArea.verticalScrollBar()
            #print v.minimum(), v.value(), v.maximum(), v.sliderPosition()
            #self.ui.scrollArea.verticalScrollBar().setValue(self.ui.scrollArea.verticalScrollBar().maximum())
            self.process_msg = None
            return

        self.ui.textEdit.setEnabled(True)
        self.ui.sendButton.setEnabled(True)
        self.ui.refreshButton.setEnabled(True)

        self.thread = thread

        if thread.root is NotLoaded:
            self._insert_load_button(0)
        else:
            for message in thread.iter_all_messages():
                self._insert_message(message)

    def _insert_message(self, message):
        widget = ThreadMessage(message)
        if widget in self.messages:
            old_widget = self.messages[self.messages.index(widget)]
            if old_widget.message.flags != widget.message.flags:
                old_widget.set_message(widget.message)
            return

        for i, m in enumerate(self.messages):
            if widget.message.date > m.message.date:
                self.ui.scrollAreaContent.layout().insertWidget(i, widget)
                self.messages.insert(i, widget)
                if message.parent is NotLoaded:
                    self._insert_load_button(i)
                return

        self.ui.scrollAreaContent.layout().addWidget(widget)
        self.messages.append(widget)
        if message.parent is NotLoaded:
            self._insert_load_button(-1)

    def _insert_load_button(self, pos):
        button = QPushButton(self.tr('More messages...'))
        self.connect(button, SIGNAL('clicked()'), lambda: self._load_button_pressed(button))
        if pos >= 0:
            self.ui.scrollAreaContent.layout().insertWidget(pos, button)
        else:
            self.ui.scrollAreaContent.layout().addWidget(button)

    def _load_button_pressed(self, button):
        self.ui.scrollAreaContent.layout().removeWidget(button)
        button.hide()
        button.deleteLater()

        self.refreshMessages(fillobj=True)

    def postReply(self):
        text = unicode(self.ui.textEdit.toPlainText())
        self.ui.textEdit.setEnabled(False)
        self.ui.sendButton.setEnabled(False)
        m = Message(thread=self.thread,
                    id=0,
                    title=u'',
                    sender=None,
                    receivers=None,
                    content=text,
                    parent=self.messages[0].message if len(self.messages) > 0 else None)
        self.process_reply = QtDo(self.weboob, self._postReply_cb, self._postReply_eb)
        self.process_reply.do('post_message', m, backends=self.contact.backend)

    def _postReply_cb(self, backend, ignored):
        if not backend:
            return
        self.ui.textEdit.clear()
        self.ui.textEdit.setEnabled(True)
        self.ui.sendButton.setEnabled(True)
        self.refreshMessages()
        self.process_reply = None

    def _postReply_eb(self, backend, error, backtrace):
        content = unicode(self.tr('Unable to send message:\n%s\n')) % error
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % backtrace
        QMessageBox.critical(self, self.tr('Error while posting reply'),
                             content, QMessageBox.Ok)
        self.process_reply = None
Пример #33
0
class MainWindow(QtMainWindow):
    def __init__(self, config, weboob, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.weboob = weboob
        self.backend = None

        self.connect(self.ui.idEdit,
                     SIGNAL("returnPressed()"),
                     self.loadPage)
        self.connect(self.ui.loadButton,
                     SIGNAL("clicked()"),
                     self.loadPage)
        self.connect(self.ui.tabWidget,
                     SIGNAL("currentChanged(int)"),
                     self._currentTabChanged)
        self.connect(self.ui.saveButton,
                     SIGNAL("clicked()"),
                     self.savePage)
        self.connect(self.ui.actionBackends,
                     SIGNAL("triggered()"),
                     self.backendsConfig)
        self.connect(self.ui.contentEdit,
                     SIGNAL("textChanged()"),
                     self._textChanged)
        self.connect(self.ui.loadHistoryButton,
                     SIGNAL("clicked()"),
                     self.loadHistory)

        if hasattr(self.ui.descriptionEdit, "setPlaceholderText"):
            self.ui.descriptionEdit.setPlaceholderText("Edit summary")

        if self.weboob.count_backends() == 0:
            self.backendsConfig()
        else:
            self.loadBackends()

    def backendsConfig(self):
        """ Opens backends configuration dialog when 'Backends' is clicked """
        bckndcfg = BackendCfg(self.weboob, (ICapContent,), self)
        if bckndcfg.run():
            self.loadBackends()

    def loadBackends(self):
        """ Fills the backends comboBox with available backends """
        self.ui.backendBox.clear()
        for backend in self.weboob.iter_backends():
            self.ui.backendBox.insertItem(0, backend.name)

    def _currentTabChanged(self):
        """ Loads history or preview when the corresponding tabs are shown """
        if self.ui.tabWidget.currentIndex() == 1:
            if self.backend is not None:
                self.loadPreview()
        elif self.ui.tabWidget.currentIndex() == 2:
            if self.backend is not None:
                self.loadHistory()

    def _textChanged(self):
        """ The text in the content QPlainTextEdit has changed """
        if self.backend:
            self.ui.saveButton.setEnabled(True)
            self.ui.saveButton.setText('Save')

    def loadPage(self):
        """ Loads a page's source into the 'content' QPlainTextEdit """
        _id = unicode(self.ui.idEdit.text())
        if not _id:
            return
        
        self.ui.loadButton.setEnabled(False)
        self.ui.loadButton.setText('Loading...')
        self.ui.contentEdit.setReadOnly(True)
                
        backend = str(self.ui.backendBox.currentText())
        self.process = QtDo(self.weboob,
                            self._loadedPage,
                            self._errorLoadPage)
        self.process.do('get_content', _id, backends=(backend,))

    def _loadedPage(self, backend, data):
        """ Callback for loadPage """
        if not backend:
            # Loading is finished
            self.process = None
            if self.backend:
                self.ui.contentEdit.setReadOnly(False)
                self.ui.loadButton.setEnabled(True)
                self.ui.loadButton.setText('Load')
            return
        if not data:
            self.content = None
            self.backend = None
            QMessageBox.critical(self, self.tr('Unable to open page'),
                                 'Unable to open page "%s" on %s: it does not exist.'
                                 % (self.ui.idEdit.text(),
                                    self.ui.backendBox.currentText()),
                                 QMessageBox.Ok)
            return

        self.content = data
        self.ui.contentEdit.setPlainText(self.content.content)
        self.setWindowTitle("QWebcontentedit - %s@%s" %(self.content.id,
                                                        backend.name))
        self.backend = backend    

    def _errorLoadPage(self, backend, error, backtrace):
        """ Error callback for loadPage """
        content = unicode(self.tr('Unable to load page:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while loading page'),
                             content, QMessageBox.Ok)
        self.ui.loadButton.setEnabled(True)
        self.ui.loadButton.setText("Load")

    def savePage(self):
        """ Saves the current page to the remote site """
        if self.backend is None:
            return
        new_content = unicode(self.ui.contentEdit.toPlainText())
        minor = self.ui.minorBox.isChecked()
        if new_content != self.content.content:
            self.ui.saveButton.setEnabled(False)
            self.ui.saveButton.setText('Saving...')
            self.ui.contentEdit.setReadOnly(True)
            self.content.content = new_content
            message = unicode(self.ui.descriptionEdit.text())
            self.process = QtDo(self.weboob,
                                self._savedPage,
                                self._errorSavePage)
            self.process.do('push_content',
                            self.content,
                            message,
                            minor=minor,
                            backends=self.backend)

    def _savedPage(self, backend, data):
        """ Callback for savePage's QtDo """
        if not backend:
            # saving has finished
            self.process = None
            self.ui.saveButton.setText('Saved')
            self.ui.contentEdit.setReadOnly(False)
            return
        self.ui.descriptionEdit.clear()

    def _errorSavePage(self, backend, error, backtrace):
        """ """
        content = unicode(self.tr('Unable to save page:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while saving page'),
                             content, QMessageBox.Ok)
        self.ui.saveButton.setEnabled(True)
        self.ui.saveButton.setText("Save")

    def loadPreview(self):
        """ Loads the current page's preview into the preview QTextEdit """
        tmp_content = deepcopy(self.content)
        tmp_content.content = unicode(self.ui.contentEdit.toPlainText())
        self.ui.previewEdit.setHtml(self.backend.get_content_preview(tmp_content))

    def loadHistory(self):
        """ Loads the page's log into the 'History' tab """
        if self.backend is None:
            return

        self.ui.loadHistoryButton.setEnabled(False)
        self.ui.loadHistoryButton.setText("Loading...")
        
        self.ui.historyTable.clear()
        self.ui.historyTable.setRowCount(0)

        self.ui.historyTable.setHorizontalHeaderLabels(["Revision",
                                                        "Time",
                                                        "Author",
                                                        "Summary"])
        self.ui.historyTable.setColumnWidth(3, 1000)
        
        self.process = QtDo(self.weboob,
                            self._gotRevision,
                            self._errorHistory)
        self.process.do('iter_revisions',
                        self.content.id,
                        max_results=self.ui.nbRevBox.value(),
                        backends=(self.backend,))

    def _gotRevision(self, backend, revision):
        """ Callback for loadHistory's QtDo """
        if not backend:
            # The last revision has been processed
            self.process = None
            self.ui.loadHistoryButton.setEnabled(True)
            self.ui.loadHistoryButton.setText("Reload")
            return

        # we set the flags to Qt.ItemIsEnabled so that the items
        # are not modifiable (they are modifiable by default)
        item_revision = QTableWidgetItem(revision.id)
        item_revision.setFlags(Qt.ItemIsEnabled)
        
        item_time = QTableWidgetItem(revision.timestamp.strftime('%Y-%m-%d %H:%M:%S'))
        item_time.setFlags(Qt.ItemIsEnabled)
        
        item_author = QTableWidgetItem(revision.author)
        item_author.setFlags(Qt.ItemIsEnabled)
        
        item_summary = QTableWidgetItem(revision.comment)
        item_summary.setFlags(Qt.ItemIsEnabled)

        row = self.ui.historyTable.currentRow() + 1
        self.ui.historyTable.insertRow(row)
        self.ui.historyTable.setItem(row, 0, item_revision)
        self.ui.historyTable.setItem(row, 1, item_time)
        self.ui.historyTable.setItem(row, 2, item_author)
        self.ui.historyTable.setItem(row, 3, item_summary)

        self.ui.historyTable.setCurrentCell(row, 0)

    def _errorHistory(self, backend, error, backtrace):
        """ Loading the history has failed """
        content = unicode(self.tr('Unable to load history:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while loading history'),
                             content, QMessageBox.Ok)
        
        self.ui.loadHistoryButton.setEnabled(True)
        self.ui.loadHistoryButton.setText("Reload")
Пример #34
0
class MainWindow(QtMainWindow):
    def __init__(self, config, storage, weboob, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.storage = storage
        self.weboob = weboob
        self.process = None
        self.displayed_photo_idx = 0
        self.process_photo = {}
        self.process_bookmarks = {}

        # search history is a list of patterns which have been searched
        self.search_history = self.loadSearchHistory()
        self.updateCompletion()

        self.ui.jobFrame.hide()

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)

        self.connect(self.ui.searchEdit, SIGNAL('returnPressed()'), self.doSearch)
        self.connect(self.ui.jobList, SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'), self.jobSelected)
        self.connect(self.ui.searchButton, SIGNAL('clicked()'), self.doSearch)

        self.connect(self.ui.refreshButton, SIGNAL('clicked()'), self.doAdvancedSearch)
        self.connect(self.ui.queriesTabWidget, SIGNAL('currentChanged(int)'), self.tabChange)
        self.connect(self.ui.jobListAdvancedSearch, SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'), self.jobSelected)

        self.connect(self.ui.idEdit, SIGNAL('returnPressed()'), self.openJob)

        if self.weboob.count_backends() == 0:
            self.backendsConfig()

    def loadSearchHistory(self):
        ''' Return search string history list loaded from history file
        '''
        result = []
        history_path = os.path.join(self.weboob.workdir, 'qhandjoob_history')
        if os.path.exists(history_path):
            f = codecs.open(history_path, 'r', 'utf-8')
            conf_hist = f.read()
            f.close()
            if conf_hist is not None and conf_hist.strip() != '':
                result = conf_hist.strip().split('\n')
        return result

    def saveSearchHistory(self):
        ''' Save search history in history file
        '''
        if len(self.search_history) > 0:
            history_path = os.path.join(self.weboob.workdir, 'qhandjoob_history')
            f = codecs.open(history_path, 'w', 'utf-8')
            f.write('\n'.join(self.search_history))
            f.close()

    def updateCompletion(self):
        qc = QCompleter(QStringList(self.search_history), self)
        qc.setCaseSensitivity(Qt.CaseInsensitive)
        self.ui.searchEdit.setCompleter(qc)

    def tabChange(self, index):
        if index == 1:
            self.doAdvancedSearch()

    def doAdvancedSearch(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.ui.jobListAdvancedSearch.clear()
        self.process = QtDo(self.weboob, self.addJobAdvancedSearch)
        self.process.do('advanced_search_job')

    def doSearch(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        pattern = unicode(self.ui.searchEdit.text())

        # arbitrary max number of completion word
        if pattern:
            if len(self.search_history) > 50:
                self.search_history.pop(0)
            if pattern not in self.search_history:
                self.search_history.append(pattern)
                self.updateCompletion()

        self.ui.jobList.clear()
        self.process = QtDo(self.weboob, self.addJobSearch)
        self.process.do('search_job', pattern)

    def addJobSearch(self, backend, job):
        item = self.addJob(backend, job)
        if item:
            self.ui.jobList.addItem(item)

        if not backend:
            QApplication.restoreOverrideCursor()

    def addJobAdvancedSearch(self, backend, job):
        item = self.addJob(backend, job)
        if item:
            self.ui.jobListAdvancedSearch.addItem(item)

        if not backend:
            QApplication.restoreOverrideCursor()

    def addJob(self, backend, job):
        if not backend:
            self.process = None
            return

        if not job:
            return

        item = JobListWidgetItem(job)
        item.setAttrs(self.storage)
        return item

    def closeEvent(self, event):
        self.saveSearchHistory()
        QtMainWindow.closeEvent(self, event)

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (ICapJob,), self)
        if bckndcfg.run():
            pass

    def jobSelected(self, item, prev):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        if item is not None:
            job = item.job
            self.ui.queriesTabWidget.setEnabled(False)

            self.process = QtDo(self.weboob, self.gotJob)
            self.process.do('fillobj', job, backends=job.backend)

        else:
            job = None

        self.setJob(job)

        if prev:
            prev.setAttrs(self.storage)

    def openJob(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        url = unicode(self.ui.idEdit.text())
        if not url:
            return

        for backend in self.weboob.iter_backends():
            job = backend.get_job_advert(url)
            if job:
                self.process = QtDo(self.weboob, self.gotJob)
                self.process.do('fillobj', job, backends=job.backend)
                break

        self.setJob(job)
        self.ui.idEdit.clear()
        QApplication.restoreOverrideCursor()

    def gotJob(self, backend, job):
        if not backend:
            self.ui.queriesTabWidget.setEnabled(True)
            self.process = None
            return

        self.setJob(job)

    def setJob(self, job):
        if job:
            self.ui.descriptionEdit.setText("%s" % job.description)
            self.ui.titleLabel.setText("<h1>%s</h1>" % job.title)
            self.ui.idLabel.setText("%s" % job.id)
            self.ui.jobNameLabel.setText("%s" % job.job_name)
            self.ui.publicationDateLabel.setText("%s" % job.publication_date)
            self.ui.societyNameLabel.setText("%s" % job.society_name)
            self.ui.placeLabel.setText("%s" % job.place)
            self.ui.payLabel.setText("%s" % job.pay)
            self.ui.contractTypeLabel.setText("%s" % job.contract_type)
            self.ui.formationLabel.setText("%s" % job.formation)
            self.ui.experienceLabel.setText("%s" % job.experience)
            self.ui.urlLabel.setText("<a href='%s'>%s</a>" % (job.url, job.url))
            self.ui.jobFrame.show()
        else:
            self.ui.jobFrame.hide()

        QApplication.restoreOverrideCursor()
Пример #35
0
class MainWindow(QtMainWindow):
    def __init__(self, config, weboob, app, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.weboob = weboob
        self.app = app
        self.minis = []
        self.current_info_widget = None

        # search history is a list of patterns which have been searched
        self.search_history = self.loadSearchHistory()
        self.updateCompletion()

        # action history is composed by the last action and the action list
        # An action is a function, a list of arguments and a description string
        self.action_history = {'last_action': None, 'action_list': []}
        self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack)
        self.ui.backButton.hide()
        self.connect(self.ui.stopButton, SIGNAL("clicked()"), self.stopProcess)
        self.ui.stopButton.hide()

        self.connect(self.ui.searchEdit, SIGNAL("returnPressed()"),
                     self.search)
        self.connect(self.ui.idEdit, SIGNAL("returnPressed()"), self.searchId)

        count = self.config.get('settings', 'maxresultsnumber')
        self.ui.countSpin.setValue(int(count))

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"),
                     self.backendsConfig)
        self.connect(self.ui.actionQuit, SIGNAL("triggered()"), self.close)

        self.loadBackendsList()

        if self.ui.backendEdit.count() == 0:
            self.backendsConfig()

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (ICapRecipe, ), self)
        if bckndcfg.run():
            self.loadBackendsList()

    def loadBackendsList(self):
        self.ui.backendEdit.clear()
        for i, backend in enumerate(self.weboob.iter_backends()):
            if i == 0:
                self.ui.backendEdit.addItem('All backends', '')
            self.ui.backendEdit.addItem(backend.name, backend.name)
            if backend.name == self.config.get('settings', 'backend'):
                self.ui.backendEdit.setCurrentIndex(i + 1)

        if self.ui.backendEdit.count() == 0:
            self.ui.searchEdit.setEnabled(False)
        else:
            self.ui.searchEdit.setEnabled(True)

    def loadSearchHistory(self):
        ''' Return search string history list loaded from history file
        '''
        result = []
        history_path = os.path.join(self.weboob.workdir, 'qcookboob_history')
        if os.path.exists(history_path):
            f = codecs.open(history_path, 'r', 'utf-8')
            conf_hist = f.read()
            f.close()
            if conf_hist is not None and conf_hist.strip() != '':
                result = conf_hist.strip().split('\n')
        return result

    def saveSearchHistory(self):
        ''' Save search history in history file
        '''
        if len(self.search_history) > 0:
            history_path = os.path.join(self.weboob.workdir,
                                        'qcookboob_history')
            f = codecs.open(history_path, 'w', 'utf-8')
            f.write('\n'.join(self.search_history))
            f.close()

    def updateCompletion(self):
        qc = QCompleter(QStringList(self.search_history), self)
        qc.setCaseSensitivity(Qt.CaseInsensitive)
        self.ui.searchEdit.setCompleter(qc)

    def getCount(self):
        num = self.ui.countSpin.value()
        if num == 0:
            return None
        else:
            return num

    def stopProcess(self):
        self.process.process.finish_event.set()

    def doAction(self, description, fun, args):
        ''' Call fun with args as arguments
        and save it in the action history
        '''
        self.ui.currentActionLabel.setText(description)
        if self.action_history['last_action'] is not None:
            self.action_history['action_list'].append(
                self.action_history['last_action'])
            self.ui.backButton.setToolTip(
                self.action_history['last_action']['description'])
            self.ui.backButton.show()
        self.action_history['last_action'] = {
            'function': fun,
            'args': args,
            'description': description
        }
        return fun(*args)

    def doBack(self):
        ''' Go back in action history
        Basically call previous function and update history
        '''
        if len(self.action_history['action_list']) > 0:
            todo = self.action_history['action_list'].pop()
            self.ui.currentActionLabel.setText(todo['description'])
            self.action_history['last_action'] = todo
            if len(self.action_history['action_list']) == 0:
                self.ui.backButton.hide()
            else:
                self.ui.backButton.setToolTip(
                    self.action_history['action_list'][-1]['description'])
            return todo['function'](*todo['args'])

    def search(self):
        pattern = unicode(self.ui.searchEdit.text())
        # arbitrary max number of completion word
        if len(self.search_history) > 50:
            self.search_history.pop(0)
        if pattern not in self.search_history:
            self.search_history.append(pattern)
            self.updateCompletion()

        self.searchRecipe()

    def searchRecipe(self):
        pattern = unicode(self.ui.searchEdit.text())
        if not pattern:
            return
        self.doAction(u'Search recipe "%s"' % pattern, self.searchRecipeAction,
                      [pattern])

    def searchRecipeAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(
            self.ui.backendEdit.itemData(
                self.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addRecipe)
        self.process.do(self.app._do_complete,
                        self.getCount(), ('title'),
                        'iter_recipes',
                        pattern,
                        backends=backend_name,
                        caps=ICapRecipe)
        self.ui.stopButton.show()

    def addRecipe(self, backend, recipe):
        if not backend:
            self.ui.searchEdit.setEnabled(True)
            QApplication.restoreOverrideCursor()
            self.process = None
            self.ui.stopButton.hide()
            return
        minirecipe = MiniRecipe(self.weboob, backend, recipe, self)
        self.ui.list_content.layout().addWidget(minirecipe)
        self.minis.append(minirecipe)

    def displayRecipe(self, recipe, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(
                self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wrecipe = Recipe(recipe, backend, self)
        self.ui.info_content.layout().addWidget(wrecipe)
        self.current_info_widget = wrecipe
        QApplication.restoreOverrideCursor()

    def searchId(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        id = unicode(self.ui.idEdit.text())
        if '@' in id:
            backend_name = id.split('@')[1]
            id = id.split('@')[0]
        else:
            backend_name = None
        for backend in self.weboob.iter_backends():
            if (backend_name
                    and backend.name == backend_name) or not backend_name:
                recipe = backend.get_recipe(id)
                if recipe:
                    self.doAction('Details of recipe "%s"' % recipe.title,
                                  self.displayRecipe, [recipe, backend])
        QApplication.restoreOverrideCursor()

    def closeEvent(self, ev):
        self.config.set(
            'settings', 'backend',
            str(
                self.ui.backendEdit.itemData(
                    self.ui.backendEdit.currentIndex()).toString()))
        self.saveSearchHistory()
        self.config.set('settings', 'maxresultsnumber',
                        self.ui.countSpin.value())

        self.config.save()
        ev.accept()
Пример #36
0
class MessagesManager(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_MessagesManager()
        self.ui.setupUi(self)

        self.weboob = weboob

        self.ui.backendsList.setCurrentRow(0)
        self.backend = None
        self.thread = None
        self.message = None

        self.ui.replyButton.setEnabled(False)
        self.ui.replyWidget.hide()

        self.connect(self.ui.backendsList, SIGNAL('itemSelectionChanged()'), self._backendChanged)
        self.connect(self.ui.threadsList,  SIGNAL('itemSelectionChanged()'), self._threadChanged)
        self.connect(self.ui.messagesTree, SIGNAL('itemClicked(QTreeWidgetItem *, int)'), self._messageSelected)
        self.connect(self.ui.messagesTree, SIGNAL('itemActivated(QTreeWidgetItem *, int)'), self._messageSelected)
        self.connect(self.ui.profileButton, SIGNAL('clicked()'), self._profilePressed)
        self.connect(self.ui.replyButton, SIGNAL('clicked()'), self._replyPressed)
        self.connect(self.ui.sendButton, SIGNAL('clicked()'), self._sendPressed)

    def load(self):
        self.ui.backendsList.clear()
        self.ui.backendsList.addItem('(All)')
        for backend in self.weboob.iter_backends():
            if not backend.has_caps(ICapMessages):
                continue

            item = QListWidgetItem(backend.name.capitalize())
            item.setData(Qt.UserRole, backend)
            self.ui.backendsList.addItem(item)

        self.refreshThreads()

    def _backendChanged(self):
        selection = self.ui.backendsList.selectedItems()
        if not selection:
            self.backend = None
            return

        self.backend = selection[0].data(Qt.UserRole).toPyObject()
        self.refreshThreads()

    def refreshThreads(self):
        self.ui.messagesTree.clear()
        self.ui.threadsList.clear()

        self.hideReply()
        self.ui.profileButton.hide()
        self.ui.replyButton.setEnabled(False)
        self.ui.backendsList.setEnabled(False)
        self.ui.threadsList.setEnabled(False)

        self.process_threads = QtDo(self.weboob, self._gotThread)
        self.process_threads.do('iter_threads', backends=self.backend, caps=ICapMessages)

    def _gotThread(self, backend, thread):
        if not backend:
            self.process_threads = None
            self.ui.backendsList.setEnabled(True)
            self.ui.threadsList.setEnabled(True)
            return

        item = QListWidgetItem(thread.title)
        item.setData(Qt.UserRole, (thread.backend, thread.id))
        self.ui.threadsList.addItem(item)

    def _threadChanged(self):
        self.ui.messagesTree.clear()
        selection = self.ui.threadsList.selectedItems()
        if not selection:
            return

        t = selection[0].data(Qt.UserRole).toPyObject()
        self.refreshThreadMessages(*t)

    def refreshThreadMessages(self, backend, id):
        self.ui.messagesTree.clear()
        self.ui.messageBody.clear()
        self.ui.backendsList.setEnabled(False)
        self.ui.threadsList.setEnabled(False)
        self.ui.replyButton.setEnabled(False)
        self.ui.profileButton.hide()
        self.hideReply()

        self.process = QtDo(self.weboob, self._gotThreadMessages)
        self.process.do('get_thread', id, backends=backend)

    def _gotThreadMessages(self, backend, thread):
        if thread is None:
            self.ui.backendsList.setEnabled(True)
            self.ui.threadsList.setEnabled(True)
            self.process = None
            return

        self.thread = thread
        if thread.flags & thread.IS_THREADS:
            top = self.ui.messagesTree.invisibleRootItem()
        else:
            top = None

        self._insert_message(thread.root, top)
        self.showMessage(thread.root)

        self.ui.messagesTree.expandAll()

    def _insert_message(self, message, top):
        item = QTreeWidgetItem(None, [message.title or '', message.sender or 'Unknown',
                                      time.strftime('%Y-%m-%d %H:%M:%S', message.date.timetuple())])
        item.setData(0, Qt.UserRole, message)
        if message.flags & message.IS_UNREAD:
            item.setForeground(0, QBrush(Qt.darkYellow))
            item.setForeground(1, QBrush(Qt.darkYellow))
            item.setForeground(2, QBrush(Qt.darkYellow))

        if top is not None:
            # threads
            top.addChild(item)
        else:
            # discussion
            self.ui.messagesTree.invisibleRootItem().insertChild(0, item)

        if message.children is not None:
            for child in message.children:
                self._insert_message(child, top and item)

    def _messageSelected(self, item, column):
        message = item.data(0, Qt.UserRole).toPyObject()

        self.showMessage(message, item)

    def showMessage(self, message, item=None):
        backend = self.weboob.get_backend(message.thread.backend)
        if backend.has_caps(ICapMessagesPost):
            self.ui.replyButton.setEnabled(True)
        self.message = message

        if message.title.startswith('Re:'):
            self.ui.titleEdit.setText(message.title)
        else:
            self.ui.titleEdit.setText('Re: %s' % message.title)

        if message.flags & message.IS_HTML:
            content = message.content
        else:
            content = message.content.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('\n', '<br />')

        extra = u''
        if message.flags & message.IS_NOT_RECEIVED:
            extra += u'<b>Status</b>: <font color=#ff0000>Unread</font><br />'
        elif message.flags & message.IS_RECEIVED:
            extra += u'<b>Status</b>: <font color=#00ff00>Read</font><br />'
        elif message.flags & message.IS_UNREAD:
            extra += u'<b>Status</b>: <font color=#0000ff>New</font><br />'

        self.ui.messageBody.setText("<h1>%s</h1>"
                                    "<b>Date</b>: %s<br />"
                                    "<b>From</b>: %s<br />"
                                    "%s"
                                    "<p>%s</p>"
                                    % (message.title, str(message.date), message.sender, extra, content))

        if item and message.flags & message.IS_UNREAD:
            backend.set_message_read(message)
            message.flags &= ~message.IS_UNREAD
            item.setForeground(0, QBrush())
            item.setForeground(1, QBrush())
            item.setForeground(2, QBrush())

        if message.thread.flags & message.thread.IS_DISCUSSION:
            self.ui.profileButton.show()
        else:
            self.ui.profileButton.hide()

    def _profilePressed(self):
        print self.thread.id
        self.emit(SIGNAL('display_contact'), self.thread.id)

    def displayReply(self):
        self.ui.replyButton.setText(self.tr('Cancel'))
        self.ui.replyWidget.show()

    def hideReply(self):
        self.ui.replyButton.setText(self.tr('Reply'))
        self.ui.replyWidget.hide()
        self.ui.replyEdit.clear()
        self.ui.titleEdit.clear()

    def _replyPressed(self):
        if self.ui.replyWidget.isVisible():
            self.hideReply()
        else:
            self.displayReply()

    def _sendPressed(self):
        if not self.ui.replyWidget.isVisible():
            return

        text = unicode(self.ui.replyEdit.toPlainText())
        title = unicode(self.ui.titleEdit.text())

        self.ui.backendsList.setEnabled(False)
        self.ui.threadsList.setEnabled(False)
        self.ui.messagesTree.setEnabled(False)
        self.ui.replyButton.setEnabled(False)
        self.ui.replyWidget.setEnabled(False)
        self.ui.sendButton.setText(self.tr('Sending...'))
        flags = 0
        if self.ui.htmlBox.currentIndex() == 0:
            flags = Message.IS_HTML
        m = Message(thread=self.thread,
                    id=0,
                    title=title,
                    sender=None,
                    receivers=None,
                    content=text,
                    parent=self.message,
                    flags=flags)
        self.process_reply = QtDo(self.weboob, self._postReply_cb, self._postReply_eb)
        self.process_reply.do('post_message', m, backends=self.thread.backend)

    def _postReply_cb(self, backend, ignored):
        if not backend:
            return

        self.ui.backendsList.setEnabled(True)
        self.ui.threadsList.setEnabled(True)
        self.ui.messagesTree.setEnabled(True)
        self.ui.replyButton.setEnabled(True)
        self.ui.replyWidget.setEnabled(True)
        self.ui.sendButton.setEnabled(True)
        self.ui.sendButton.setText(self.tr('Send'))
        self.hideReply()
        self.process_reply = None
        self.refreshThreadMessages(backend.name, self.thread.id)

    def _postReply_eb(self, backend, error, backtrace):
        content = unicode(self.tr('Unable to send message:\n%s\n')) % to_unicode(error)
        if logging.root.level == logging.DEBUG:
            content += '\n%s\n' % to_unicode(backtrace)
        QMessageBox.critical(self, self.tr('Error while posting reply'),
                             content, QMessageBox.Ok)
        self.ui.backendsList.setEnabled(True)
        self.ui.threadsList.setEnabled(True)
        self.ui.messagesTree.setEnabled(True)
        self.ui.replyButton.setEnabled(True)
        self.ui.replyWidget.setEnabled(True)
        self.ui.sendButton.setText(self.tr('Send'))
        self.process_reply = None
Пример #37
0
class EventsWidget(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Events()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.photo_processes = {}
        self.event_filter = None

        self.connect(self.ui.eventsList,
                     SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'),
                     self.eventDoubleClicked)
        self.connect(self.ui.typeBox, SIGNAL('currentIndexChanged(int)'),
                     self.typeChanged)
        self.connect(self.ui.refreshButton, SIGNAL('clicked()'),
                     self.refreshEventsList)

        self.ui.eventsList.setItemDelegate(HTMLDelegate())
        self.ui.eventsList.sortByColumn(1, Qt.DescendingOrder)

    def load(self):
        self.refreshEventsList()

    def typeChanged(self, i):
        if self.ui.refreshButton.isEnabled():
            self.refreshEventsList()

    def refreshEventsList(self):
        self.ui.eventsList.clear()
        self.ui.refreshButton.setEnabled(False)
        if self.ui.typeBox.currentIndex() >= 0:
            # XXX strangely, in gotEvent() in the loop to check if there is already the
            # event type to try to introduce it in list, itemData() returns the right value.
            # But, I don't know why, here, it will ALWAYS return None...
            # So the filter does not work currently.
            self.events_filter = self.ui.typeBox.itemData(
                self.ui.typeBox.currentIndex())
        else:
            self.event_filter = None
        self.ui.typeBox.setEnabled(False)
        self.ui.typeBox.clear()
        self.ui.typeBox.addItem('All', None)
        self.process = QtDo(self.weboob, self.gotEvent)
        self.process.do('iter_events')

    def setPhoto(self, contact, item):
        if not contact:
            return False

        try:
            self.photo_processes.pop(contact.id, None)
        except KeyError:
            pass

        img = None
        for photo in contact.photos.itervalues():
            if photo.thumbnail_data:
                img = QImage.fromData(photo.thumbnail_data)
                break

        if img:
            item.setIcon(0, QIcon(QPixmap.fromImage(img)))
            self.ui.eventsList.resizeColumnToContents(0)
            return True

        return False

    def gotEvent(self, backend, event):
        if not backend:
            self.ui.refreshButton.setEnabled(True)
            self.ui.typeBox.setEnabled(True)
            return

        found = False
        for i in xrange(self.ui.typeBox.count()):
            s = self.ui.typeBox.itemData(i)
            if s == event.type:
                found = True
        if not found:
            print event.type
            self.ui.typeBox.addItem(event.type.capitalize(), event.type)
            if event.type == self.event_filter:
                self.ui.typeBox.setCurrentIndex(self.ui.typeBox.count() - 1)

        if self.event_filter and self.event_filter != event.type:
            return

        contact = event.contact
        contact.backend = event.backend
        status = ''

        if contact.status == contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        name = '<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' % (
            contact.name, status_color, status, event.backend)
        date = event.date.strftime('%Y-%m-%d %H:%M')
        type = event.type
        message = event.message

        item = QTreeWidgetItem(None, [name, date, type, message])
        item.setData(0, Qt.UserRole, event)
        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj',
                       contact, ['photos'],
                       backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob,
                               lambda b, p: self.setPhoto(contact, item))
                process.do('fillobj',
                           photo, ['thumbnail_data'],
                           backends=contact.backend)
                self.photo_processes[contact.id] = process

        self.ui.eventsList.addTopLevelItem(item)
        self.ui.eventsList.resizeColumnToContents(0)
        self.ui.eventsList.resizeColumnToContents(1)

    def eventDoubleClicked(self, item, col):
        event = item.data(0, Qt.UserRole).toPyObject()
        self.emit(SIGNAL('display_contact'), event.contact)
Пример #38
0
class QueryDialog(QDialog):
    def __init__(self, weboob, parent=None):
        QDialog.__init__(self, parent)
        self.ui = Ui_QueryDialog()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.ui.resultsList.setItemDelegate(HTMLDelegate())
        self.ui.citiesList.setItemDelegate(HTMLDelegate())

        self.search_process = None

        self.connect(self.ui.cityEdit, SIGNAL('returnPressed()'), self.searchCity)
        self.connect(self.ui.resultsList, SIGNAL('itemDoubleClicked(QListWidgetItem*)'), self.insertCity)
        self.connect(self.ui.citiesList, SIGNAL('itemDoubleClicked(QListWidgetItem*)'), self.removeCity)
        self.connect(self.ui.buttonBox, SIGNAL('accepted()'), self.okButton)

        if hasattr(self.ui.cityEdit, "setPlaceholderText"):
            self.ui.cityEdit.setPlaceholderText("Press enter to search city")

    def keyPressEvent(self, event):
        """
        Disable handler <Enter> and <Escape> to prevent closing the window.
        """
        event.ignore()

    def selectComboValue(self, box, value):
        for i in xrange(box.count()):
            if box.itemText(i) == str(value):
                box.setCurrentIndex(i)
                break

    def searchCity(self):
        pattern = unicode(self.ui.cityEdit.text())
        self.ui.resultsList.clear()
        self.ui.cityEdit.clear()
        self.ui.cityEdit.setEnabled(False)

        self.search_process = QtDo(self.weboob, self.addResult, fb=self.addResultEnd)
        self.search_process.do('search_city', pattern)

    def addResultEnd(self):
        self.search_process = None
        self.ui.cityEdit.setEnabled(True)

    def addResult(self, city):
        if not city:
            return
        item = self.buildCityItem(city)
        self.ui.resultsList.addItem(item)
        self.ui.resultsList.sortItems()

    def buildCityItem(self, city):
        item = QListWidgetItem()
        item.setText('<b>%s</b> (%s)' % (city.name, city.backend))
        item.setData(Qt.UserRole, city)
        return item

    def insertCity(self, i):
        item = QListWidgetItem()
        item.setText(i.text())
        item.setData(Qt.UserRole, i.data(Qt.UserRole))
        self.ui.citiesList.addItem(item)

    def removeCity(self, item):
        self.ui.citiesList.removeItemWidget(item)

    def okButton(self):
        if not self.ui.nameEdit.text():
            QMessageBox.critical(self, self.tr('Error'), self.tr('Please enter a name to your query.'), QMessageBox.Ok)
            return

        if self.ui.citiesList.count() == 0:
            QMessageBox.critical(self, self.tr('Error'), self.tr('Please add at least one city.'), QMessageBox.Ok)
            return

        self.accept()
Пример #39
0
class MainWindow(QtMainWindow):
    def __init__(self, config, storage, weboob, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.storage = storage
        self.weboob = weboob
        self.process = None
        self.displayed_photo_idx = 0
        self.process_photo = {}
        self.process_bookmarks = {}

        self.ui.jobFrame.hide()

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)
        self.connect(self.ui.searchEdit, SIGNAL('returnPressed()'), self.doSearch)
        self.connect(self.ui.jobList, SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'), self.jobSelected)
        self.connect(self.ui.searchButton, SIGNAL('clicked()'), self.doSearch)

        if self.weboob.count_backends() == 0:
            self.backendsConfig()

    def doSearch(self):
        pattern = unicode(self.ui.searchEdit.text())
        self.ui.jobList.clear()
        self.process = QtDo(self.weboob, self.addJob)
        self.process.do('search_job', pattern)

    def addJob(self, backend, job):
        if not backend:
            self.process = None
            return

        if not job:
            return

        item = JobListWidgetItem(job)
        item.setAttrs(self.storage)
        self.ui.jobList.addItem(item)

    def closeEvent(self, event):
        QtMainWindow.closeEvent(self, event)

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (ICapJob,), self)
        if bckndcfg.run():
            pass

    def jobSelected(self, item, prev):
        if item is not None:
            job = item.job
            self.ui.queriesFrame.setEnabled(False)

            self.process = QtDo(self.weboob, self.gotJob)
            self.process.do('fillobj', job, backends=job.backend)

        else:
            job = None

        self.setJob(job)

        if prev:
            prev.setAttrs(self.storage)

    def gotJob(self, backend, job):
        if not backend:
            self.ui.queriesFrame.setEnabled(True)
            self.process = None
            return

        self.setJob(job)

    def setJob(self, job):
        if job:
            self.ui.descriptionEdit.setText("%s" % job.description)
            self.ui.titleLabel.setText("<h1>%s</h1>" % job.title)
            self.ui.backendLabel.setText("%s" % job.backend)
            self.ui.jobNameLabel.setText("%s" % job.job_name)
            self.ui.publicationDateLabel.setText("%s" % job.publication_date)
            self.ui.societyNameLabel.setText("%s" % job.society_name)
            self.ui.placeLabel.setText("%s" % job.place)
            self.ui.payLabel.setText("%s" % job.pay)
            self.ui.contractTypeLabel.setText("%s" % job.contract_type)
            self.ui.formationLabel.setText("%s" % job.formation)
            self.ui.experienceLabel.setText("%s" % job.experience)
            self.ui.urlLabel.setText("<a href='%s'>%s</a>" % (job.url, job.url))
            self.ui.jobFrame.show()
        else:
            self.ui.jobFrame.hide()
Пример #40
0
    def gotEvent(self, backend, event):
        if not backend:
            self.ui.refreshButton.setEnabled(True)
            self.ui.typeBox.setEnabled(True)
            return

        found = False
        for i in xrange(self.ui.typeBox.count()):
            s = self.ui.typeBox.itemData(i)
            if s == event.type:
                found = True
        if not found:
            print event.type
            self.ui.typeBox.addItem(event.type.capitalize(), event.type)
            if event.type == self.event_filter:
                self.ui.typeBox.setCurrentIndex(self.ui.typeBox.count() - 1)

        if self.event_filter and self.event_filter != event.type:
            return

        contact = event.contact
        contact.backend = event.backend
        status = ''

        if contact.status == contact.STATUS_ONLINE:
            status = u'Online'
            status_color = 0x00aa00
        elif contact.status == contact.STATUS_OFFLINE:
            status = u'Offline'
            status_color = 0xff0000
        elif contact.status == contact.STATUS_AWAY:
            status = u'Away'
            status_color = 0xffad16
        else:
            status = u'Unknown'
            status_color = 0xaaaaaa

        if contact.status_msg:
            status += u' — %s' % contact.status_msg

        name = '<h2>%s</h2><font color="#%06X">%s</font><br /><i>%s</i>' % (
            contact.name, status_color, status, event.backend)
        date = event.date.strftime('%Y-%m-%d %H:%M')
        type = event.type
        message = event.message

        item = QTreeWidgetItem(None, [name, date, type, message])
        item.setData(0, Qt.UserRole, event)
        if contact.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj',
                       contact, ['photos'],
                       backends=contact.backend)
            self.photo_processes[contact.id] = process
        elif len(contact.photos) > 0:
            if not self.setPhoto(contact, item):
                photo = contact.photos.values()[0]
                process = QtDo(self.weboob,
                               lambda b, p: self.setPhoto(contact, item))
                process.do('fillobj',
                           photo, ['thumbnail_data'],
                           backends=contact.backend)
                self.photo_processes[contact.id] = process

        self.ui.eventsList.addTopLevelItem(item)
        self.ui.eventsList.resizeColumnToContents(0)
        self.ui.eventsList.resizeColumnToContents(1)
Пример #41
0
class QueryDialog(QDialog):
    def __init__(self, weboob, parent=None):
        QDialog.__init__(self, parent)
        self.ui = Ui_QueryDialog()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.ui.resultsList.setItemDelegate(HTMLDelegate())
        self.ui.citiesList.setItemDelegate(HTMLDelegate())

        self.search_process = None

        self.connect(self.ui.cityEdit, SIGNAL('returnPressed()'),
                     self.searchCity)
        self.connect(self.ui.resultsList,
                     SIGNAL('itemDoubleClicked(QListWidgetItem*)'),
                     self.insertCity)
        self.connect(self.ui.citiesList,
                     SIGNAL('itemDoubleClicked(QListWidgetItem*)'),
                     self.removeCity)
        self.connect(self.ui.buttonBox, SIGNAL('accepted()'), self.okButton)

        if hasattr(self.ui.cityEdit, "setPlaceholderText"):
            self.ui.cityEdit.setPlaceholderText("Press enter to search city")

    def keyPressEvent(self, event):
        """
        Disable handler <Enter> and <Escape> to prevent closing the window.
        """
        event.ignore()

    def selectComboValue(self, box, value):
        for i in xrange(box.count()):
            if box.itemText(i) == str(value):
                box.setCurrentIndex(i)
                break

    def searchCity(self):
        pattern = unicode(self.ui.cityEdit.text())
        self.ui.resultsList.clear()
        self.ui.cityEdit.clear()
        self.ui.cityEdit.setEnabled(False)

        self.search_process = QtDo(self.weboob,
                                   self.addResult,
                                   fb=self.addResultEnd)
        self.search_process.do('search_city', pattern)

    def addResultEnd(self):
        self.search_process = None
        self.ui.cityEdit.setEnabled(True)

    def addResult(self, city):
        if not city:
            return
        item = self.buildCityItem(city)
        self.ui.resultsList.addItem(item)
        self.ui.resultsList.sortItems()

    def buildCityItem(self, city):
        item = QListWidgetItem()
        item.setText('<b>%s</b> (%s)' % (city.name, city.backend))
        item.setData(Qt.UserRole, city)
        return item

    def insertCity(self, i):
        item = QListWidgetItem()
        item.setText(i.text())
        item.setData(Qt.UserRole, i.data(Qt.UserRole))
        self.ui.citiesList.addItem(item)

    def removeCity(self, item):
        self.ui.citiesList.removeItemWidget(item)

    def okButton(self):
        if not self.ui.nameEdit.text():
            QMessageBox.critical(self, self.tr('Error'),
                                 self.tr('Please enter a name to your query.'),
                                 QMessageBox.Ok)
            return

        if self.ui.citiesList.count() == 0:
            QMessageBox.critical(self, self.tr('Error'),
                                 self.tr('Please add at least one city.'),
                                 QMessageBox.Ok)
            return

        self.accept()
Пример #42
0
class MainWindow(QtMainWindow):
    def __init__(self, config, storage, weboob, parent=None):
        QtMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.config = config
        self.storage = storage
        self.weboob = weboob
        self.process = None
        self.housing = None
        self.displayed_photo_idx = 0
        self.process_photo = {}
        self.process_bookmarks = {}

        self.ui.housingsList.setItemDelegate(HTMLDelegate())
        self.ui.housingFrame.hide()

        self.connect(self.ui.actionBackends, SIGNAL("triggered()"), self.backendsConfig)
        self.connect(self.ui.queriesList, SIGNAL('currentIndexChanged(int)'), self.queryChanged)
        self.connect(self.ui.addQueryButton, SIGNAL('clicked()'), self.addQuery)
        self.connect(self.ui.editQueryButton, SIGNAL('clicked()'), self.editQuery)
        self.connect(self.ui.removeQueryButton, SIGNAL('clicked()'), self.removeQuery)
        self.connect(self.ui.bookmarksButton, SIGNAL('clicked()'), self.displayBookmarks)
        self.connect(self.ui.housingsList, SIGNAL('currentItemChanged(QListWidgetItem*, QListWidgetItem*)'), self.housingSelected)
        self.connect(self.ui.previousButton, SIGNAL('clicked()'), self.previousClicked)
        self.connect(self.ui.nextButton, SIGNAL('clicked()'), self.nextClicked)
        self.connect(self.ui.bookmark, SIGNAL('stateChanged(int)'), self.bookmarkChanged)

        self.reloadQueriesList()
        self.refreshHousingsList()

        if self.weboob.count_backends() == 0:
            self.backendsConfig()

        if len(self.config.get('queries')) == 0:
            self.addQuery()

    def closeEvent(self, event):
        self.setHousing(None)
        QtMainWindow.closeEvent(self, event)

    def backendsConfig(self):
        bckndcfg = BackendCfg(self.weboob, (ICapHousing,), self)
        if bckndcfg.run():
            pass

    def reloadQueriesList(self, select_name=None):
        self.disconnect(self.ui.queriesList, SIGNAL('currentIndexChanged(int)'), self.queryChanged)
        self.ui.queriesList.clear()
        for name in self.config.get('queries', default={}).iterkeys():
            self.ui.queriesList.addItem(name)
            if name == select_name:
                self.ui.queriesList.setCurrentIndex(len(self.ui.queriesList)-1)
        self.connect(self.ui.queriesList, SIGNAL('currentIndexChanged(int)'), self.queryChanged)

        if select_name is not None:
            self.queryChanged()

    def removeQuery(self):
        name = unicode(self.ui.queriesList.itemText(self.ui.queriesList.currentIndex()))
        queries = self.config.get('queries')
        queries.pop(name, None)
        self.config.set('queries', queries)
        self.config.save()

        self.reloadQueriesList()
        self.queryChanged()

    def editQuery(self):
        name = unicode(self.ui.queriesList.itemText(self.ui.queriesList.currentIndex()))
        self.addQuery(name)

    def addQuery(self, name=None):
        querydlg = QueryDialog(self.weboob, self)
        if name is not None:
            query = self.config.get('queries', name)
            querydlg.ui.nameEdit.setText(name)
            querydlg.ui.nameEdit.setEnabled(False)
            for c in query['cities']:
                city = City(c['id'])
                city.backend = c['backend']
                city.name = c['name']
                item = querydlg.buildCityItem(city)
                querydlg.ui.citiesList.addItem(item)

            querydlg.ui.typeBox.setCurrentIndex(int(query.get('type', 0)))
            querydlg.ui.areaMin.setValue(query['area_min'])
            querydlg.ui.areaMax.setValue(query['area_max'])
            querydlg.ui.costMin.setValue(query['cost_min'])
            querydlg.ui.costMax.setValue(query['cost_max'])
            querydlg.selectComboValue(querydlg.ui.nbRooms, query['nb_rooms'])

        if querydlg.exec_():
            name = unicode(querydlg.ui.nameEdit.text())
            query = {}
            query['type'] = querydlg.ui.typeBox.currentIndex()
            query['cities'] = []
            for i in xrange(len(querydlg.ui.citiesList)):
                item = querydlg.ui.citiesList.item(i)
                city = item.data(Qt.UserRole).toPyObject()
                query['cities'].append({'id': city.id, 'backend': city.backend, 'name': city.name})
            query['area_min'] = querydlg.ui.areaMin.value()
            query['area_max'] = querydlg.ui.areaMax.value()
            query['cost_min'] = querydlg.ui.costMin.value()
            query['cost_max'] = querydlg.ui.costMax.value()
            try:
                query['nb_rooms'] = int(querydlg.ui.nbRooms.itemText(querydlg.ui.nbRooms.currentIndex()))
            except ValueError:
                query['nb_rooms'] = 0
            self.config.set('queries', name, query)
            self.config.save()

            self.reloadQueriesList(name)

    def queryChanged(self, i=None):
        self.refreshHousingsList()

    def refreshHousingsList(self):
        name = unicode(self.ui.queriesList.itemText(self.ui.queriesList.currentIndex()))
        q = self.config.get('queries', name)

        if q is None:
            return q

        self.ui.housingsList.clear()
        self.ui.queriesList.setEnabled(False)
        self.ui.bookmarksButton.setEnabled(False)

        query = Query()
        query.type = int(q.get('type', 0))
        query.cities = []
        for c in q['cities']:
            city = City(c['id'])
            city.backend = c['backend']
            city.name = c['name']
            query.cities.append(city)

        query.area_min = int(q['area_min']) or None
        query.area_max = int(q['area_max']) or None
        query.cost_min = int(q['cost_min']) or None
        query.cost_max = int(q['cost_max']) or None
        query.nb_rooms = int(q['nb_rooms']) or None

        self.process = QtDo(self.weboob, self.addHousing)
        self.process.do('search_housings', query)

    def displayBookmarks(self):
        self.ui.housingsList.clear()
        self.ui.queriesList.setEnabled(False)
        self.ui.queriesList.setCurrentIndex(-1)
        self.ui.bookmarksButton.setEnabled(False)

        self.processes = {}
        for id in self.storage.get('bookmarks'):
            _id, backend_name = id.rsplit('@', 1)
            self.process_bookmarks[id] = QtDo(self.weboob, self.addHousing)
            self.process_bookmarks[id].do('get_housing', _id, backends=backend_name)

    def addHousing(self, backend, housing):
        if not backend:
            self.ui.queriesList.setEnabled(True)
            self.ui.bookmarksButton.setEnabled(True)
            self.process = None
            return

        if not housing:
            return

        item = HousingListWidgetItem(housing)
        item.setAttrs(self.storage)

        if housing.photos is NotLoaded:
            process = QtDo(self.weboob, lambda b, c: self.setPhoto(c, item))
            process.do('fillobj', housing, ['photos'], backends=housing.backend)
            self.process_photo[housing.id] = process
        elif housing.photos is not NotAvailable and len(housing.photos) > 0:
            if not self.setPhoto(housing, item):
                photo = housing.photos[0]
                process = QtDo(self.weboob, lambda b, p: self.setPhoto(housing, item))
                process.do('fillobj', photo, ['data'], backends=housing.backend)
                self.process_photo[housing.id] = process

        self.ui.housingsList.addItem(item)

        if housing.fullid in self.process_bookmarks:
            self.process_bookmarks.pop(housing.fullid)

    def housingSelected(self, item, prev):
        if item is not None:
            housing = item.housing
            self.ui.queriesFrame.setEnabled(False)

            read = set(self.storage.get('read'))
            read.add(housing.fullid)
            self.storage.set('read', list(read))
            self.storage.save()

            self.process = QtDo(self.weboob, self.gotHousing)
            self.process.do('fillobj', housing, backends=housing.backend)

        else:
            housing = None

        self.setHousing(housing)

        if prev:
            prev.setAttrs(self.storage)

    def setPhoto(self, housing, item):
        if not housing:
            return False

        try:
            self.process_photo.pop(housing.id, None)
        except KeyError:
            pass

        if not housing.photos:
            return False

        img = None
        for photo in housing.photos:
            if photo.data:
                img = QImage.fromData(photo.data)
                break

        if img:
            item.setIcon(QIcon(QPixmap.fromImage(img)))
            return True

        return False


    def setHousing(self, housing, nottext='Loading...'):
        if self.housing is not None:
            self.saveNotes()

        self.housing = housing

        if self.housing is None:
            self.ui.housingFrame.hide()
            return

        self.ui.housingFrame.show()

        self.display_photo()

        self.ui.bookmark.setChecked(housing.fullid in self.storage.get('bookmarks'))

        self.ui.titleLabel.setText('<h1>%s</h1>' % housing.title)
        self.ui.areaLabel.setText(u'%s m²' % housing.area)
        self.ui.costLabel.setText(u'%s %s' % (housing.cost, housing.currency))
        self.ui.dateLabel.setText(housing.date.strftime('%Y-%m-%d') if housing.date else nottext)
        self.ui.phoneLabel.setText(housing.phone or nottext)
        self.ui.locationLabel.setText(housing.location or nottext)
        self.ui.stationLabel.setText(housing.station or nottext)

        if housing.text:
            self.ui.descriptionEdit.setText(housing.text.replace('\n', '<br/>'))
        else:
            self.ui.descriptionEdit.setText(nottext)

        self.ui.notesEdit.setText(self.storage.get('notes', housing.fullid, default=''))

        while self.ui.detailsFrame.layout().count() > 0:
            child = self.ui.detailsFrame.layout().takeAt(0)
            child.widget().hide()
            child.widget().deleteLater()

        if housing.details:
            for key, value in housing.details.iteritems():
                label = QLabel(value)
                label.setTextInteractionFlags(Qt.TextSelectableByMouse|Qt.LinksAccessibleByMouse)
                self.ui.detailsFrame.layout().addRow('<b>%s:</b>' % key, label)

    def gotHousing(self, backend, housing):
        if not backend:
            self.ui.queriesFrame.setEnabled(True)
            self.process = None
            return

        self.setHousing(housing, nottext='')

    def bookmarkChanged(self, state):
        bookmarks = set(self.storage.get('bookmarks'))
        if state == Qt.Checked:
            bookmarks.add(self.housing.fullid)
        elif self.housing.fullid in bookmarks:
            bookmarks.remove(self.housing.fullid)
        self.storage.set('bookmarks', list(bookmarks))
        self.storage.save()

    def saveNotes(self):
        if not self.housing:
            return
        txt = unicode(self.ui.notesEdit.toPlainText()).strip()
        if len(txt) > 0:
            self.storage.set('notes', self.housing.fullid, txt)
        else:
            self.storage.delete('notes', self.housing.fullid)
        self.storage.save()

    def previousClicked(self):
        if not self.housing.photos or len(self.housing.photos) == 0:
            return
        self.displayed_photo_idx = (self.displayed_photo_idx - 1) % len(self.housing.photos)
        self.display_photo()

    def nextClicked(self):
        if not self.housing.photos or len(self.housing.photos) == 0:
            return
        self.displayed_photo_idx = (self.displayed_photo_idx + 1) % len(self.housing.photos)
        self.display_photo()

    def display_photo(self):
        if not self.housing.photos:
            self.ui.photosFrame.hide()
            return

        if self.displayed_photo_idx >= len(self.housing.photos):
            self.displayed_photo_idx = len(self.housing.photos) - 1
        if self.displayed_photo_idx < 0:
            self.ui.photosFrame.hide()
            return

        self.ui.photosFrame.show()

        photo = self.housing.photos[self.displayed_photo_idx]
        if photo.data:
            data = photo.data
            if photo.id in self.process_photo:
                self.process_photo.pop(photo.id)
        else:
            self.process_photo[photo.id] = QtDo(self.weboob, lambda b,p: self.display_photo())
            self.process_photo[photo.id].do('fillobj', photo, ['data'], backends=self.housing.backend)

            return

        img = QImage.fromData(data)
        img = img.scaledToWidth(self.width()/3)

        self.ui.photoLabel.setPixmap(QPixmap.fromImage(img))
        if photo.url is not NotLoaded:
            text = '<a href="%s">%s</a>' % (photo.url, photo.url)
            self.ui.photoUrlLabel.setText(text)
Пример #43
0
class Result(QFrame):
    def __init__(self, weboob, app, parent=None):
        QFrame.__init__(self, parent)
        self.ui = Ui_Result()
        self.ui.setupUi(self)

        self.parent = parent
        self.weboob = weboob
        self.app = app
        self.minis = []
        self.current_info_widget = None

        # action history is composed by the last action and the action list
        # An action is a function, a list of arguments and a description string
        self.action_history = {'last_action': None, 'action_list': []}
        self.connect(self.ui.backButton, SIGNAL("clicked()"), self.doBack)
        self.ui.backButton.hide()

    def doAction(self, description, fun, args):
        ''' Call fun with args as arguments
        and save it in the action history
        '''
        self.ui.currentActionLabel.setText(description)
        if self.action_history['last_action'] is not None:
            self.action_history['action_list'].append(self.action_history['last_action'])
            self.ui.backButton.setToolTip(self.action_history['last_action']['description'])
            self.ui.backButton.show()
        self.action_history['last_action'] = {'function': fun, 'args': args, 'description': description}
        return fun(*args)

    def doBack(self):
        ''' Go back in action history
        Basically call previous function and update history
        '''
        if len(self.action_history['action_list']) > 0:
            todo = self.action_history['action_list'].pop()
            self.ui.currentActionLabel.setText(todo['description'])
            self.action_history['last_action'] = todo
            if len(self.action_history['action_list']) == 0:
                self.ui.backButton.hide()
            else:
                self.ui.backButton.setToolTip(self.action_history['action_list'][-1]['description'])
            return todo['function'](*todo['args'])

    def castingAction(self, backend_name, id, role):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.process = QtDo(self.weboob, self.addPerson, fb=self.processFinished)
        self.process.do('iter_movie_persons', id, role, backends=backend_name, caps=CapCinema)
        self.parent.ui.stopButton.show()

    def filmographyAction(self, backend_name, id, role):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.process = QtDo(self.weboob, self.addMovie, fb=self.processFinished)
        self.process.do('iter_person_movies', id, role, backends=backend_name, caps=CapCinema)
        self.parent.ui.stopButton.show()

    def search(self, tosearch, pattern, lang):
        if tosearch == 'person':
            self.searchPerson(pattern)
        elif tosearch == 'movie':
            self.searchMovie(pattern)
        elif tosearch == 'torrent':
            self.searchTorrent(pattern)
        elif tosearch == 'subtitle':
            self.searchSubtitle(lang, pattern)

    def searchMovie(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search movie "%s"' % pattern, self.searchMovieAction, [pattern])

    def searchMovieAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addMovie, fb=self.processFinished)
        #self.process.do('iter_movies', pattern, backends=backend_name, caps=CapCinema)
        self.process.do(self.app._do_complete, self.parent.getCount(), ('original_title'), 'iter_movies', pattern, backends=backend_name, caps=CapCinema)
        self.parent.ui.stopButton.show()

    def stopProcess(self):
        self.process.process.finish_event.set()

    def addMovie(self, movie):
        minimovie = MiniMovie(self.weboob, self.weboob[movie.backend], movie, self)
        self.ui.list_content.layout().addWidget(minimovie)
        self.minis.append(minimovie)

    def displayMovie(self, movie, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wmovie = Movie(movie, backend, self)
        self.ui.info_content.layout().addWidget(wmovie)
        self.current_info_widget = wmovie
        QApplication.restoreOverrideCursor()

    def searchPerson(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search person "%s"' % pattern, self.searchPersonAction, [pattern])

    def searchPersonAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addPerson, fb=self.processFinished)
        #self.process.do('iter_persons', pattern, backends=backend_name, caps=CapCinema)
        self.process.do(self.app._do_complete, self.parent.getCount(), ('name'), 'iter_persons', pattern, backends=backend_name, caps=CapCinema)
        self.parent.ui.stopButton.show()

    def addPerson(self, person):
        miniperson = MiniPerson(self.weboob, self.weboob[person.backend], person, self)
        self.ui.list_content.layout().addWidget(miniperson)
        self.minis.append(miniperson)

    def displayPerson(self, person, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wperson = Person(person, backend, self)
        self.ui.info_content.layout().addWidget(wperson)
        self.current_info_widget = wperson
        QApplication.restoreOverrideCursor()

    def searchTorrent(self, pattern):
        if not pattern:
            return
        self.doAction(u'Search torrent "%s"' % pattern, self.searchTorrentAction, [pattern])

    def searchTorrentAction(self, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addTorrent, fb=self.processFinished)
        #self.process.do('iter_torrents', pattern, backends=backend_name, caps=CapTorrent)
        self.process.do(self.app._do_complete, self.parent.getCount(), ('name'), 'iter_torrents', pattern, backends=backend_name, caps=CapTorrent)
        self.parent.ui.stopButton.show()

    def processFinished(self):
        self.parent.ui.searchEdit.setEnabled(True)
        QApplication.restoreOverrideCursor()
        self.process = None
        self.parent.ui.stopButton.hide()

    def addTorrent(self, torrent):
        minitorrent = MiniTorrent(self.weboob, self.weboob[torrent.backend], torrent, self)
        self.ui.list_content.layout().addWidget(minitorrent)
        self.minis.append(minitorrent)

    def displayTorrent(self, torrent, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wtorrent = Torrent(torrent, backend, self)
        self.ui.info_content.layout().addWidget(wtorrent)
        self.current_info_widget = wtorrent

    def searchSubtitle(self, lang, pattern):
        if not pattern:
            return
        self.doAction(u'Search subtitle "%s" (lang:%s)' % (pattern, lang), self.searchSubtitleAction, [lang, pattern])

    def searchSubtitleAction(self, lang, pattern):
        self.ui.stackedWidget.setCurrentWidget(self.ui.list_page)
        for mini in self.minis:
            self.ui.list_content.layout().removeWidget(mini)
            mini.hide()
            mini.deleteLater()

        self.minis = []
        self.parent.ui.searchEdit.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        backend_name = str(self.parent.ui.backendEdit.itemData(self.parent.ui.backendEdit.currentIndex()).toString())

        self.process = QtDo(self.weboob, self.addSubtitle, fb=self.processFinished)
        #self.process.do('iter_subtitles', lang, pattern, backends=backend_name, caps=CapSubtitle)
        self.process.do(self.app._do_complete, self.parent.getCount(), ('name'), 'iter_subtitles', lang, pattern, backends=backend_name, caps=CapSubtitle)
        self.parent.ui.stopButton.show()

    def addSubtitle(self, subtitle):
        minisubtitle = MiniSubtitle(self.weboob, self.weboob[subtitle.backend], subtitle, self)
        self.ui.list_content.layout().addWidget(minisubtitle)
        self.minis.append(minisubtitle)

    def displaySubtitle(self, subtitle, backend):
        self.ui.stackedWidget.setCurrentWidget(self.ui.info_page)
        if self.current_info_widget is not None:
            self.ui.info_content.layout().removeWidget(self.current_info_widget)
            self.current_info_widget.hide()
            self.current_info_widget.deleteLater()
        wsubtitle = Subtitle(subtitle, backend, self)
        self.ui.info_content.layout().addWidget(wsubtitle)
        self.current_info_widget = wsubtitle

    def searchId(self, id, stype):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        title_field = 'name'
        if stype == 'movie':
            cap = CapCinema
            title_field = 'original_title'
        elif stype == 'person':
            cap = CapCinema
        elif stype == 'torrent':
            cap = CapTorrent
        elif stype == 'subtitle':
            cap = CapSubtitle
        if '@' in id:
            backend_name = id.split('@')[1]
            id = id.split('@')[0]
        else:
            backend_name = None
        for backend in self.weboob.iter_backends():
            if backend.has_caps(cap) and ((backend_name and backend.name == backend_name) or not backend_name):
                exec('object = backend.get_%s(id)' % (stype))
                if object:
                    func_display = 'self.display' + stype[0].upper() + stype[1:]
                    exec("self.doAction('Details of %s \"%%s\"' %% object.%s, %s, [object, backend])" %
                            (stype, title_field, func_display))
        QApplication.restoreOverrideCursor()
Пример #44
0
class SearchWidget(QWidget):
    def __init__(self, weboob, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_Search()
        self.ui.setupUi(self)

        self.weboob = weboob
        self.contacts = []
        self.accounts = []
        self.current = None

        self.connect(self.ui.nextButton, SIGNAL('clicked()'), self.next)
        self.connect(self.ui.queryButton, SIGNAL('clicked()'), self.sendQuery)

    def load(self):
        while self.ui.statusFrame.layout().count() > 0:
            item = self.ui.statusFrame.layout().takeAt(0)
            if item.widget():
                item.widget().deinit()
                item.widget().hide()
                item.widget().deleteLater()

        self.accounts = []

        for backend in self.weboob.iter_backends():
            account = Account(self.weboob, backend)
            account.title.setText(u'<h2>%s</h2>' % backend.name)
            self.accounts.append(account)
            self.ui.statusFrame.layout().addWidget(account)
        self.ui.statusFrame.layout().addStretch()

        self.getNewProfiles()

    def updateStats(self):
        for account in self.accounts:
            account.updateStats()

    def getNewProfiles(self):
        self.newprofiles_process = QtDo(self.weboob, self.retrieveNewContacts_cb)
        self.newprofiles_process.do('iter_new_contacts')

    def retrieveNewContacts_cb(self, contact):
        self.contacts.insert(0, contact)
        self.ui.queueLabel.setText('%d' % len(self.contacts))
        if self.current is None:
            self.next()

    def next(self):
        try:
            contact = self.contacts.pop()
        except IndexError:
            contact = None

        self.ui.queueLabel.setText('%d' % len(self.contacts))
        self.setContact(contact)
        self.updateStats()

    def setContact(self, contact):
        self.current = contact
        if contact is not None:
            widget = ContactProfile(self.weboob, contact)
            self.ui.scrollArea.setWidget(widget)
        else:
            self.ui.scrollArea.setWidget(None)

    def sendQuery(self):
        self.newprofiles_process = QtDo(self.weboob, None, fb=self.next)
        self.newprofiles_process.do('send_query', self.current.id, backends=[self.current.backend])