vpackager / src / vpackager / viewcontrollers.py

#!/usr/bin/env python

#    This file is part of vpackager.
#
#    vpackager is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License v3 as published by
#    the Free Software Foundation.
#
#    vpackager is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with vpackager.  If not, see <http://www.gnu.org/licenses/>.


import gtk
import dbutils
import dbviews
import guitools
import os

__author__ = 'M0E-lnx'
__author_email__ = 'moc.liamg@xnl.E0M'[::-1]
__version__ = '0.1'

class QueueController(object):
    """ Controller for the queue view"""
    def __init__(self, model, view):
        self.model = model
        self.view = view
        self.setup_observers()
        self._parentwindow = self.view.get_parent_window()
        self.connect_signals()
        self.refresh_view()

    def refresh_view(self):
        self._show_queue()

    def setup_observers(self):
        self.model.add_observer(
            self.view.Update_TableView, table='queue')
        return

    def connect_signals(self):
        # Connect buttons
        self.view.connect_item('about_job', self._about_job_event)
        self.view.connect_item('add_job', self._add_job_event)
        self.view.connect_item('remove_job', self._delete_job_event)
        # connect right-click menu items
        self.view.rc_menu.connect_item('job_details', self._about_job_event)
        self.view.rc_menu.connect_item('delete_job', self._delete_job_event)
        self.view.rc_menu.connect_item('edit_job', self._edit_job_event)

    def _edit_job_event(self, widget=None):
        """ Edit an existing job in the queue"""
        dia = guitools.JobAddDialog(
            title = 'Edit job', parent = self._parentwindow)
        cur_details = self.model.GetJobDetails(self.view._selectedjob)
        dia.set_src(cur_details['srcURI'])
        dia.set_desc(cur_details['descURI'])
        dia.set_app(cur_details['app'])
        dia.set_version(cur_details['ver'])
        dia.set_patches(cur_details['patches'].split(','))
        dia.set_config(cur_details['config'])
        dia.set_doinst(cur_details['doinstURI'])
        # Determine the source type and pre-set it back on the drop box
        _type = cur_details['type']
        if _type == 'autotools':
            _typeid = 1
        elif _type == 'python':
            _typeid = 2
        elif _type == 'cmake':
            _typeid = 3
        elif _type == 'perl':
            _typeid = 4
        elif _type == 'waf':
            _typeid = 5
        else:
            _typeid = 0
        # Set the dropbox value to the determined source type
        dia.srcTypeSel.set_active(_typeid)
        # Set the install? checkbox value
        dia.cbinstallpkg.set_active(cur_details['install'] == '1')

        res = dia.run()
        dia.hide()
        if res == gtk.RESPONSE_OK:
            ret = self.model.UpdateJob(
                _id = cur_details['id'],
                app = dia.app,
                ver = dia.ver,
                srcURI = dia.SrcURI,
                descURI = dia.DescURI,
                release = dia.release,
                _type = dia.srctype,
                install = dia.install,
                doinstURI = dia.doinstURI,
                config_options = dia.config_options,
                patches = ','.join(dia.patches))
            if ret is True:
                # Something went wrong, maybe the bot was running and the
                # job got processed before it could be edited
                dia = guitools.message.Error(
                    text = "The job could not be edited. This can happen "+\
                           "when the job is processed before changes are saved",
                    parent = self._parentwindow)
                if dia.run():
                    dia.destroy()
        return

    def _show_queue(self, widget=None):
        """ Force the queue to be displayed"""
        return self.model.RefreshQueue()

    def _about_job_event(self, widget=None):
        """ Display a dialog showing detailed information about a queued job"""
        dia = guitools.AboutJob(parent = self._parentwindow,
                                jobid=self.view._selectedjob)
        if dia.run():
            dia.destroy()

    def _delete_job_event(self, widget=None):
        return self.model.DeleteJob(self.view._selectedjob)

    def _add_job_event(self, widget=None):
        """ Display a dialog to add a new job to the queue"""
        dia = guitools.JobAddDialog(parent=self._parentwindow)
        res = dia.run()
        dia.hide()

        if res == gtk.RESPONSE_OK:
            ret = self.model.NewJob(
                app = dia.app,
                ver = dia.ver,
                srcURI = dia.SrcURI,
                descURI = dia.DescURI,
                release = dia.release,
                _type = dia.srctype,
                install = dia.install,
                patches = ','.join(dia.patches),
                doinstURI = dia.doinstURI,
                config_options = dia.config_options)

        else:
            ret = dia.destroy
        return ret

class HistoryController(QueueController):
    """ Controller for the history view """
    def __init__(self, model, view):
        self.model = model
        self.view = view
        QueueController.__init__(self, self.model, self.view)

    def setup_observers(self):
        """ Connect observers to the signalers"""
        self.model.add_observer(self.view.Update_TableView, table='history')

    def refresh_view(self):
        """ Refreh the GUI representation of the history"""
        return self.model.RefreshHistory()

    def apply_filter(self, widget=None, filter=None):
        """ Filter the job history"""
        return self.model.FilterHistory(filter)

    def connect_signals(self):
        """ Connect signals to different widgets that are exposed from the
        view object"""
        # Connect buttons
        self.view.connect_item('about_task', self._about_task_event)
        self.view.connect_item('wipe_history', self._wipe_history_event)
        self.view.connect_item('filter_all', self.apply_filter, 'all')
        self.view.connect_item('filter_successful', self.apply_filter,
                               'successful')
        self.view.connect_item('filter_failed', self.apply_filter, 'failed')
        # Connect menu items.
        self.view.rc_menu.connect_item('about_job', self._about_task_event)
        self.view.rc_menu.connect_item('rebuild_job', self._rebuild_job_event)
        self.view.rc_menu.connect_item('view_build_log',
                                       self._view_build_log_event)
        # Connect the searchbox.
        box = self.view.exposed_widgets['searchbox']
        box.connect('icon_press', self.searchbox_icon_press)
        box.connect('changed', self.searchbox_text_changed)

    def searchbox_icon_press(self, widget=None, icon=None, event=None):
        """ Defines what happend when the buttons on the search box are
        clicked"""
        if icon == gtk.ENTRY_ICON_SECONDARY:
            widget.set_text('')
            self.apply_filter(filter='all')
        else:
            if widget.get_text() == '':
                return self.apply_filter(filter='all')
            return self.model.SearchHistoryByApp(widget.get_text())

    def searchbox_text_changed(self, widget=None):
        """ Filter the job history when text is entered in the searchbox"""
        if widget.get_text() == '' :
            return self.apply_filter(filter='all')
        else:
            return self.model.SearchHistoryByApp(widget.get_text())

    def _view_build_log_event(self, widget=None):
        """ Display the build log if it is still present"""
        details = self.model.GetTaskDetails(self.view._selectedjob)
        if not details['stdout']:
            dia = guitools.message.Error(
                text = 'Build log for this job is not available.',
                parent = self._parentwindow)
            if dia.run():
                return dia.destroy()
        elif not os.path.exists(details['stdout']):
            dia = guitools.message.Error(
                parent = self._parentwindow,
                text = \
                "Build log is no longer available in the system. " +\
                "This usually means the file was deleted.",
                )
        else:
            dia = guitools.LogDisplay(
                title = '%s build log'% details['app'],
                parent = self._parentwindow,
                logpath = details['stdout'])

        if dia.run():
            return dia.destroy()

    def _about_task_event(self, widget=None):
        """ Show build details about the selected job"""
        about = guitools.AboutTask(
            jobid=self.view._selectedjob, dbase = self.model,
            parent = self._parentwindow)
        if about.run():
            about.destroy()

    def _wipe_history_event(self, widget=None):
        """ Ask if the user is sure about wiping the history, and then do it"""
        question = guitools.message.Question(
            text="Are you sure you want to delete the job history?",
            parent = self._parentwindow)
        response = question.run()
        question.destroy()
        if response == gtk.RESPONSE_YES:
            return self.model.WipeHistory()
        return

    def _rebuild_job_event(self, widget=None):
        """ Present a form to make a few changes to the job and
        add it back to the queue"""
        info = self.model.GetTaskDetails(self.view._selectedjob)
        dia = guitools.JobAddDialog(
            title = 'Rebuild %s'% info['app'],
            parent = self._parentwindow)
        dia.set_app(info['app'])
        dia.set_version(info['ver'])
        dia.set_src(info['srcURI'])
        dia.set_desc(info['descURI'])
        dia.set_config(info['config'])
        dia.set_doinst(info['doinstURI'])
        if info['patches'] not in (
            '', None, 'None'):
            dia.set_patches(info['patches'].split(','))
        response = dia.run()
        dia.hide()
        if response == gtk.RESPONSE_OK:
            ret = self.model.NewJob(
                app = dia.app,
                ver = dia.ver,
                srcURI = dia.SrcURI,
                descURI = dia.DescURI,
                release = dia.release,
                _type = dia.srctype,
                install = dia.install,
		doinstURI = dia.doinstURI,
		config_options = dia.config_options,
                patches = ','.join(dia.patches))
        else:
            ret = None
        dia.destroy()

        return ret

if __name__ == "__main__":
    model = dbutils.dbase()
    view = dbviews.HistoryView()
    control = HistoryController(model = model,
                              view = view)
    control.Run()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.