Exemple #1
0
def send_data(text, full_info, subject="", network_send=True):
    '''
    Sends the data to our servers through a post request
    '''
    files = {}
    # packs all the information into 'files'
    if full_info:
        files['report'] = get_metadata_archive()
    # This is the actual info: subject, text, email, username
    payload = {
        "text": text,
        "email": get_email(),
        "username": get_mixed_username(),
        "category": "os",
        "subject": subject
    }

    if not network_send:
        return True, None

    # send the bug report and remove all the created files
    success, error, data = request_wrapper('post', '/feedback',
                                           data=payload, files=files)
    delete_tmp_dir()

    if not success:
        return False, error
    if full_info:
        # kano-profile stat collection
        increment_app_state_variable_with_dialog('kano-feedback',
                                                 'bugs_submitted', 1)
        # logs were sent, clean up
        logging.cleanup()

    return True, None
Exemple #2
0
def share(filename):
    # TODO: Move this connection handling into a function in Kano Utils
    import subprocess

    if not is_internet():
        subprocess.call(['sudo', 'kano-settings', '4'])

    if not is_internet():
        return 'You have no internet'

    success, _ = login_using_token()
    if not success:
        os.system('kano-login 3')
        success, _ = login_using_token()
        if not success:
            return 'Cannot login'

    data = json.loads(request.data)
    filename, filepath = _save(data)
    success, msg = upload_share(filepath, filename, APP_NAME)

    if not success:
        return msg

    increment_app_state_variable_with_dialog(APP_NAME, 'shared', 1)

    return ''
Exemple #3
0
def _increment_lines_of_code():
    data = json.loads(request.data)
    new_lines = data["newLines"]

    increment_app_state_variable_with_dialog(APP_NAME, "lines_of_code", new_lines)

    return ""
Exemple #4
0
def launch_boot_gui():
    # FIXME: This window uses Gtk2 which requires the other Gtk imports to be
    #        loaded in the scope of the functions that require them.
    old_status = clean(dry_run=True)
    status = UpdaterStatus.get_instance()

    if old_status == UpdaterStatus.INSTALLING_UPDATES:
        status.notifications_muted = True
        status.state = UpdaterStatus.UPDATES_AVAILABLE
        status.save()

        remove_pid_file()

        cmd_args = ['kano-updater', 'install', '--gui', '--no-confirm']
        os.execvp('kano-updater', cmd_args)

    elif old_status == UpdaterStatus.UPDATES_INSTALLED:
        try:
            from kano_profile.badges import \
                increment_app_state_variable_with_dialog
            increment_app_state_variable_with_dialog(
                'kano-updater', 'updated', 1)
        except Exception:
            pass

        from kano_updater.ui.changes_dialog import ChangesDialog
        win = ChangesDialog()
        win.run()

    status.save()
Exemple #5
0
def share(filename):
    # TODO: Move this connection handling into a function in Kano Utils
    import subprocess

    if not is_internet():
        subprocess.call(['sudo', 'kano-settings', '4'])

    if not is_internet():
        return 'You have no internet'

    success, _ = login_using_token()
    if not success:
        os.system('kano-login 3')
        success, _ = login_using_token()
        if not success:
            return 'Cannot login'

    data = json.loads(request.data)
    filename, filepath = _save(data)
    success, msg = upload_share(filepath, filename, APP_NAME)

    if not success:
        return msg

    increment_app_state_variable_with_dialog(APP_NAME, 'shared', 1)

    return ''
Exemple #6
0
def _increment_lines_of_code():
    data = json.loads(request.data)
    new_lines = data['newLines']

    increment_app_state_variable_with_dialog(APP_NAME, 'lines_of_code',
                                             new_lines)

    return ''
def send_data(text, full_info, subject='', network_send=True, logs_path=''):
    """Sends the data to our servers through a post request.

    It uses :func:`~get_metadata_archive` to gather all the logs on
    the system.

    Args:
        text (str): The description of the email when sending the logs
        full_info (bool): Whether to attach all logs to the payload
        subject (str): The title of the email when sending the logs
        network_send (bool): Whether to send the data to our servers
        logs_path (str): Path to an existing logs archive to use instead

    Returns:
        bool, error: Whether the operation was successful or there was
        an error as returned by :func:`kano_world.functions.request_wrapper`
    """

    from kano_world.functions import get_email, get_mixed_username

    files = {}
    # packs all the information into 'files'
    if full_info:
        if logs_path and os.path.exists(logs_path):
            files['report'] = open(logs_path, 'rb')
        else:
            files['report'] = get_metadata_archive(title=subject, desc=text)
    # This is the actual info: subject, text, email, username
    payload = {
        "text": text,
        "email": get_email(),
        "username": get_mixed_username(),
        "category": "os",
        "subject": subject
    }

    if not network_send:
        return True, None

    # send the bug report and remove all the created files
    success, error, data = request_wrapper('post',
                                           '/feedback',
                                           data=payload,
                                           files=files)
    delete_tmp_dir()

    if not success:
        return False, error
    if full_info:
        # kano-profile stat collection
        from kano_profile.badges import increment_app_state_variable_with_dialog
        increment_app_state_variable_with_dialog('kano-feedback',
                                                 'bugs_submitted', 1)
        # logs were sent, clean up
        logging.cleanup()

    return True, None
def send_data(text, full_info, subject='', network_send=True, logs_path=''):
    """Sends the data to our servers through a post request.

    It uses :func:`~get_metadata_archive` to gather all the logs on
    the system.

    Args:
        text (str): The description of the email when sending the logs
        full_info (bool): Whether to attach all logs to the payload
        subject (str): The title of the email when sending the logs
        network_send (bool): Whether to send the data to our servers
        logs_path (str): Path to an existing logs archive to use instead

    Returns:
        bool, error: Whether the operation was successful or there was
        an error as returned by :func:`kano_world.functions.request_wrapper`
    """

    from kano_world.functions import get_email, get_mixed_username

    files = {}
    # packs all the information into 'files'
    if full_info:
        if logs_path and os.path.exists(logs_path):
            files['report'] = open(logs_path, 'rb')
        else:
            files['report'] = get_metadata_archive(title=subject, desc=text)
    # This is the actual info: subject, text, email, username
    payload = {
        "text": text,
        "email": get_email(),
        "username": get_mixed_username(),
        "category": "os",
        "subject": subject
    }

    if not network_send:
        return True, None

    # send the bug report and remove all the created files
    success, error, data = request_wrapper('post', '/feedback',
                                           data=payload, files=files)
    delete_tmp_dir()

    if not success:
        return False, error
    if full_info:
        # kano-profile stat collection
        from kano_profile.badges import increment_app_state_variable_with_dialog
        increment_app_state_variable_with_dialog('kano-feedback',
                                                 'bugs_submitted', 1)
        # logs were sent, clean up
        logging.cleanup()

    return True, None
Exemple #9
0
def share_theme():
    # Check for internet
    if not is_internet():
        coloured_error, junk1, junk2 = run_cmd(
            'colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip('\n') + _(
            'You need internet connection')
        exit(2)
    # Check for login
    success, junk2 = login_using_token()
    if not success:
        coloured_error, junk1, junk2 = run_cmd(
            'colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip('\n') + _(
            'You need to login to Kano World')
        exit(2)
    # Print themes
    print_themes(False, False)
    # Select theme dialogue
    message = _("    1) Select a theme: ")
    theme = raw_input(message)
    theme += '.xml'
    # Check theme exists
    check_valid_theme(theme)
    # Select title
    message = _("    2) Write a title: ")
    title = raw_input(message)
    if title:
        # The API limits title to 200 characters (cut it here)
        title = title[:200]
    else:
        title = 'My snake'
    # Select description
    message = _("    3) Write a description: ")
    description = raw_input(message)
    if description:
        # The API limits description to 500 characters (cut it here)
        description = description[:500]
    # Create json
    create_share_json(theme, title, description)
    # Share
    filepath = os.path.join(app_dir, theme)
    success, msg = upload_share(filepath, title, 'make-snake')
    if not success:
        coloured_error, junk1, junk2 = run_cmd(
            'colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip(
            '\n') + _('Sharing of {} failed. {}\n') % (theme, msg)
        exit(2)
    message, junk1, junk2 = run_cmd(
        'colour_echo "{{4 + }} {{3 You have shared your theme successfully }}"'
    )
    print "\n    " + message.strip('\n')
    increment_app_state_variable_with_dialog('make-snake', 'shared', 1)
    exit(2)
Exemple #10
0
def share_theme():
    # Check for internet
    if not is_internet():
        coloured_error, _, _ = run_cmd('colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip(
            '\n') + 'You need internet connection'
        exit(2)
    # Check for login
    success, _ = login_using_token()
    if not success:
        coloured_error, _, _ = run_cmd('colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip(
            '\n') + 'You need to login to Kano World'
        exit(2)
    # Print themes
    print_themes(False, False)
    # Select theme dialogue
    message = "    1) Select a theme: "
    theme = raw_input(message)
    theme += '.xml'
    # Check theme exists
    check_valid_theme(theme)
    # Select title
    message = "    2) Write a title: "
    title = raw_input(message)
    if not title:
        title = 'My snake'
    # Select description
    message = "    3) Write a description: "
    description = raw_input(message)
    # Create json
    create_share_json(theme, title, description)
    # Share
    filepath = os.path.join(app_dir, theme)
    success, msg = upload_share(filepath, title, 'make-snake')
    if not success:
        coloured_error, _, _ = run_cmd('colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip(
            '\n') + 'Sharing of %s failed. %s\n' % (theme, msg)
        exit(2)
    message, _, _ = run_cmd(
        'colour_echo "{{4 + }} {{3 You have shared your theme successfully }}"'
    )
    print "\n    " + message.strip('\n')
    increment_app_state_variable_with_dialog('make-snake', 'shared', 1)
    exit(2)
Exemple #11
0
def launch_boot_gui():
    # FIXME: This window uses Gtk2 which requires the other Gtk imports to be
    #        loaded in the scope of the functions that require them.
    old_status = clean(dry_run=True)
    status = UpdaterStatus.get_instance()

    if old_status == UpdaterStatus.INSTALLING_UPDATES:
        from kano.gtk3.kano_dialog import KanoDialog
        d = KanoDialog(
            'Continue updating',
            'The update you started didn\'t finish. Would you like to '
            'continue?',
            [{"label": "YES", "return_value": True, "color": "green"}],
            orange_info={'name': 'SKIP', 'return_value': False},
        )
        rv = d.run()
        del d

        if rv:
            status.notifications_muted = True
            status.state = UpdaterStatus.NO_UPDATES
            status.save()

            remove_pid_file()

            cmd_args = ['kano-updater', 'install', '--gui', '--no-confirm']
            os.execvp('kano-updater', cmd_args)

    elif old_status == UpdaterStatus.UPDATES_INSTALLED:
        try:
            from kano_profile.badges import \
                increment_app_state_variable_with_dialog
            increment_app_state_variable_with_dialog(
                'kano-updater', 'updated', 1)
        except Exception:
            pass

        from kano_updater.ui.changes_dialog import ChangesDialog
        win = ChangesDialog()
        win.run()

    status.save()
Exemple #12
0
def share(filename):
    # TODO: Move this connection handling into a function in Kano Utils
    import subprocess

    if not is_internet():
        subprocess.call(["sudo", "kano-settings", "4"])

    if not is_internet():
        return "You have no internet"

    data = json.loads(request.data)
    filename, filepath = _save(data)
    success, msg = login_and_share(filepath, filename, APP_NAME)

    if not success:
        return msg

    increment_app_state_variable_with_dialog(APP_NAME, "shared", 1)

    return ""
Exemple #13
0
def share_theme():
    # Check for internet
    if not is_internet():
        coloured_error, _, _ = run_cmd('colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip('\n') + 'You need internet connection'
        exit(2)
    # Check for login
    success, _ = login_using_token()
    if not success:
        coloured_error, _, _ = run_cmd('colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip('\n') + 'You need to login to Kano World'
        exit(2)
    # Print themes
    print_themes(False, False)
    # Select theme dialogue
    message = "    1) Select a theme: "
    theme = raw_input(message)
    theme += '.xml'
    # Check theme exists
    check_valid_theme(theme)
    # Select title
    message = "    2) Write a title: "
    title = raw_input(message)
    if not title:
        title = 'My snake'
    # Select description
    message = "    3) Write a description: "
    description = raw_input(message)
    # Create json
    create_share_json(theme, title, description)
    # Share
    filepath = os.path.join(app_dir, theme)
    success, msg = upload_share(filepath, title, 'make-snake')
    if not success:
        coloured_error, _, _ = run_cmd('colour_echo "{{8 x }} {{7 error: }}"')
        print "\n    " + coloured_error.strip('\n') + 'Sharing of %s failed. %s\n' % (theme, msg)
        exit(2)
    message, _, _ = run_cmd('colour_echo "{{4 + }} {{3 You have shared your theme successfully }}"')
    print "\n    " + message.strip('\n')
    increment_app_state_variable_with_dialog('make-snake', 'shared', 1)
    exit(2)
Exemple #14
0
def update_profile_stats():
    update_upwards_with_dialog('make-snake', 'longest_snake',
                               STATUS['longest_snake'])
    update_upwards_with_dialog('make-snake', 'highest_score',
                               STATUS['highest_score'])
    increment_app_state_variable_with_dialog('make-snake', 'total_length',
                                             STATUS['total_length'])
    increment_app_state_variable_with_dialog('make-snake',
                                             'total_number_of_apples',
                                             STATUS['total_number_of_apples'])
    increment_app_state_variable_with_dialog('make-snake', 'total_score',
                                             STATUS['total_score'])
Exemple #15
0
def update_profile_stats():
    update_upwards_with_dialog(
        'make-snake', 'longest_snake', STATUS['longest_snake']
    )
    update_upwards_with_dialog(
        'make-snake', 'highest_score', STATUS['highest_score']
    )
    increment_app_state_variable_with_dialog(
        'make-snake', 'total_length', STATUS['total_length']
    )
    increment_app_state_variable_with_dialog(
        'make-snake', 'total_number_of_apples', STATUS['total_number_of_apples']
    )
    increment_app_state_variable_with_dialog(
        'make-snake', 'total_score', STATUS['total_score']
    )
    def report_window(self):
        '''
        Report window
        Contains 2 text views and Take Screenshot, Add Image and Send buttons
        '''
        ApplicationWindow.__init__(self, _('Report a Problem'), self.WIDTH,
                                   0.35)

        screen = Gdk.Screen.get_default()
        specific_provider = Gtk.CssProvider()
        specific_provider.load_from_path(Media.media_dir() + 'css/style.css')
        style_context = Gtk.StyleContext()
        style_context.add_provider_for_screen(screen, specific_provider,
                                              Gtk.STYLE_PROVIDER_PRIORITY_USER)

        self.set_icon_name("feedback")
        self._grid = Gtk.Grid()

        # Create top bar
        self._top_bar = TopBar(title=_("Report a Problem"),
                               window_width=self.WIDTH,
                               has_buttons=False)
        self._top_bar.set_close_callback(Gtk.main_quit)
        self.set_decorated(True)
        self.set_titlebar(self._top_bar)

        self.entry = Gtk.Entry()
        self.entry.props.placeholder_text = _("Add subject (optional)")
        self.entry.set_margin_left(20)
        self.entry.set_margin_right(20)
        self.entry.set_margin_top(20)
        self.entry.set_margin_bottom(10)
        self._grid.attach(self.entry, 0, 0, 1, 1)

        # Create Text view
        self._text = Gtk.TextView()
        self._text.set_editable(True)
        self._text.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self._text.set_size_request(self.WIDTH, -1)

        self._textbuffer = self._text.get_buffer()
        self._textbuffer.set_text(_("Type your problem here!"))

        self._clear_buffer_handler_id = self._textbuffer.connect(
            "insert-text", self.clear_buffer)

        scrolledwindow = ScrolledWindow()
        scrolledwindow.set_vexpand(True)
        scrolledwindow.set_policy(Gtk.PolicyType.NEVER,
                                  Gtk.PolicyType.AUTOMATIC)
        scrolledwindow.apply_styling_to_widget()
        scrolledwindow.add(self._text)
        scrolledwindow.set_margin_left(2)
        scrolledwindow.set_margin_right(2)
        scrolledwindow.set_margin_top(2)
        scrolledwindow.set_margin_bottom(2)

        # Very hacky way to get a border: create a grey event box
        # which is a little bigger than the widget below
        border = Gtk.EventBox()
        border.get_style_context().add_class("grey")
        border.add(scrolledwindow)
        self._grid.attach(border, 0, 1, 1, 1)
        border.set_margin_left(20)
        border.set_margin_right(20)
        border.set_margin_top(10)
        border.set_margin_bottom(20)

        # Create take screenshot button
        self._screenshot_button = KanoButton(_("TAKE SCREENSHOT"), "blue")
        self._screenshot_button.set_sensitive(True)
        self._screenshot_button.connect("button_press_event",
                                        self.screenshot_clicked)

        # Create attach screenshot button
        self._attach_button = KanoButton(_("ADD IMAGE"), "blue")
        self._attach_button.set_sensitive(True)
        self._attach_button.connect("button_press_event", self.attach_clicked)

        # Create send button
        self._send_button = KanoButton(_("SEND"))
        self._send_button.set_sensitive(False)
        self._send_button.connect("button_press_event", self.send_feedback)
        self._send_button.pack_and_align()
        self._send_button.set_margin(10, 0, 10, 0)

        self.screenshot_box = Gtk.ButtonBox()
        self.screenshot_box.set_layout(Gtk.ButtonBoxStyle.CENTER)
        self.screenshot_box.set_spacing(20)
        self.pack_screenshot_buttons()
        self.screenshot_box.set_margin_bottom(20)

        self._grid.attach(self.screenshot_box, 0, 2, 1, 1)

        # Create grey box to put the button in
        self.bottom_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.bottom_box.pack_start(self._send_button.align, False, False, 0)

        bottom_background = Gtk.EventBox()
        bottom_background.get_style_context().add_class("grey")
        bottom_background.add(self.bottom_box)

        self._grid.attach(bottom_background, 0, 3, 1, 1)

        self._grid.set_row_spacing(0)
        self.set_main_widget(self._grid)

        # kano-profile stat collection
        try:
            from kano_profile.badges import increment_app_state_variable_with_dialog
            increment_app_state_variable_with_dialog('kano-feedback', 'starts',
                                                     1)
        except Exception:
            pass
Exemple #17
0
    def contact_window(self):
        '''
        Contact Us window
        Contains text view and a Send button
        '''
        # delete the directory containing all the info we'll send, and recreate
        delete_tmp_dir()
        create_tmp_dir()

        ApplicationWindow.__init__(self, 'Contact Us', self.WIDTH, 0.35)

        screen = Gdk.Screen.get_default()
        specific_provider = Gtk.CssProvider()
        specific_provider.load_from_path(Media.media_dir() + 'css/style.css')
        style_context = Gtk.StyleContext()
        style_context.add_provider_for_screen(screen, specific_provider,
                                              Gtk.STYLE_PROVIDER_PRIORITY_USER)

        # Make sure this window has no icon in the task bar
        # so it plays nice with kdesk-blur
        self.set_property('skip-taskbar-hint', True)

        self._grid = Gtk.Grid()

        # Create top bar
        self._top_bar = TopBar(title="Contact Us", window_width=self.WIDTH,
                               has_buttons=False)
        self._top_bar.set_close_callback(Gtk.main_quit)
        self.set_decorated(True)
        self.set_titlebar(self._top_bar)

        # Create Text view
        self._text = Gtk.TextView()
        self._text.set_editable(True)
        self._text.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self._text.set_size_request(self.WIDTH, -1)

        self._textbuffer = self._text.get_buffer()
        self._textbuffer.set_text("Type your feedback here!")
        self._clear_buffer_handler_id = self._textbuffer.connect("insert-text",
                                                                 self.clear_buffer)

        scrolledwindow = ScrolledWindow()
        scrolledwindow.set_vexpand(True)
        scrolledwindow.set_policy(Gtk.PolicyType.NEVER,
                                  Gtk.PolicyType.AUTOMATIC)
        scrolledwindow.apply_styling_to_widget()
        scrolledwindow.add(self._text)
        scrolledwindow.set_margin_left(2)
        scrolledwindow.set_margin_right(2)
        scrolledwindow.set_margin_top(2)
        scrolledwindow.set_margin_bottom(2)

        # Very hacky way to get a border: create a grey event box
        # which is a little bigger than the widget below
        border = Gtk.EventBox()
        border.get_style_context().add_class("grey")
        border.add(scrolledwindow)
        self._grid.attach(border, 0, 0, 1, 1)
        border.set_margin_left(20)
        border.set_margin_right(20)
        border.set_margin_top(10)
        border.set_margin_bottom(20)

        # Create send button
        self._send_button = KanoButton("SEND")
        self._send_button.set_sensitive(False)
        self._send_button.connect("button_press_event", self.send_feedback)
        self._send_button.pack_and_align()
        self._send_button.align.set_padding(10, 10, 0, 0)

        bottom_background = Gtk.EventBox()
        bottom_background.get_style_context().add_class("grey")
        bottom_background.add(self._send_button.align)

        self._grid.attach(bottom_background, 0, 1, 1, 1)

        self._grid.set_row_spacing(0)
        self.set_main_widget(self._grid)

        # kano-profile stat collection
        try:
            from kano_profile.badges import increment_app_state_variable_with_dialog
            increment_app_state_variable_with_dialog('kano-feedback', 'starts', 1)
        except Exception:
            pass
Exemple #18
0
    def report_window(self):
        '''
        Report window
        Contains 2 text views and Take Screenshot, Add Image and Send buttons
        '''
        ApplicationWindow.__init__(self, 'Report a Problem', self.WIDTH, 0.35)

        screen = Gdk.Screen.get_default()
        specific_provider = Gtk.CssProvider()
        specific_provider.load_from_path(Media.media_dir() + 'css/style.css')
        style_context = Gtk.StyleContext()
        style_context.add_provider_for_screen(screen, specific_provider,
                                              Gtk.STYLE_PROVIDER_PRIORITY_USER)

        self.set_icon_name("feedback")
        self._grid = Gtk.Grid()

        # Create top bar
        self._top_bar = TopBar(title="Report a Problem",
                               window_width=self.WIDTH, has_buttons=False)
        self._top_bar.set_close_callback(Gtk.main_quit)
        self.set_decorated(True)
        self.set_titlebar(self._top_bar)

        self.entry = Gtk.Entry()
        self.entry.props.placeholder_text = "Add subject (optional)"
        self.entry.set_margin_left(20)
        self.entry.set_margin_right(20)
        self.entry.set_margin_top(20)
        self.entry.set_margin_bottom(10)
        self._grid.attach(self.entry, 0, 0, 1, 1)

        # Create Text view
        self._text = Gtk.TextView()
        self._text.set_editable(True)
        self._text.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self._text.set_size_request(self.WIDTH, -1)

        self._textbuffer = self._text.get_buffer()
        self._textbuffer.set_text("Type your problem here!")

        self._clear_buffer_handler_id = self._textbuffer.connect("insert-text",
                                                                 self.clear_buffer)

        scrolledwindow = ScrolledWindow()
        scrolledwindow.set_vexpand(True)
        scrolledwindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
        scrolledwindow.apply_styling_to_widget()
        scrolledwindow.add(self._text)
        scrolledwindow.set_margin_left(2)
        scrolledwindow.set_margin_right(2)
        scrolledwindow.set_margin_top(2)
        scrolledwindow.set_margin_bottom(2)

        # Very hacky way to get a border: create a grey event box
        # which is a little bigger than the widget below
        border = Gtk.EventBox()
        border.get_style_context().add_class("grey")
        border.add(scrolledwindow)
        self._grid.attach(border, 0, 1, 1, 1)
        border.set_margin_left(20)
        border.set_margin_right(20)
        border.set_margin_top(10)
        border.set_margin_bottom(20)

        # Create take screenshot button
        self._screenshot_button = KanoButton("TAKE SCREENSHOT", "blue")
        self._screenshot_button.set_sensitive(True)
        self._screenshot_button.connect("button_press_event",
                                        self.screenshot_clicked)

        # Create attach screenshot button
        self._attach_button = KanoButton("ADD IMAGE", "blue")
        self._attach_button.set_sensitive(True)
        self._attach_button.connect("button_press_event", self.attach_clicked)

        # Create send button
        self._send_button = KanoButton("SEND")
        self._send_button.set_sensitive(False)
        self._send_button.connect("button_press_event", self.send_feedback)
        self._send_button.pack_and_align()
        self._send_button.set_margin(10, 0, 10, 0)

        self.screenshot_box = Gtk.ButtonBox()
        self.screenshot_box.set_layout(Gtk.ButtonBoxStyle.CENTER)
        self.screenshot_box.set_spacing(20)
        self.pack_screenshot_buttons()
        self.screenshot_box.set_margin_bottom(20)

        self._grid.attach(self.screenshot_box, 0, 2, 1, 1)

        # Create grey box to put the button in
        self.bottom_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.bottom_box.pack_start(self._send_button.align, False, False, 0)

        bottom_background = Gtk.EventBox()
        bottom_background.get_style_context().add_class("grey")
        bottom_background.add(self.bottom_box)

        self._grid.attach(bottom_background, 0, 3, 1, 1)

        self._grid.set_row_spacing(0)
        self.set_main_widget(self._grid)

        # kano-profile stat collection
        try:
            from kano_profile.badges import increment_app_state_variable_with_dialog
            increment_app_state_variable_with_dialog('kano-feedback', 'starts', 1)
        except Exception:
            pass
    def contact_window(self):
        '''
        Contact Us window
        Contains text view and a Send button
        '''
        # delete the directory containing all the info we'll send, and recreate
        delete_tmp_dir()
        create_tmp_dir()

        ApplicationWindow.__init__(self, _('Contact Us'), self.WIDTH, 0.35)

        screen = Gdk.Screen.get_default()
        specific_provider = Gtk.CssProvider()
        specific_provider.load_from_path(Media.media_dir() + 'css/style.css')
        style_context = Gtk.StyleContext()
        style_context.add_provider_for_screen(screen, specific_provider,
                                              Gtk.STYLE_PROVIDER_PRIORITY_USER)

        # Make sure this window has no icon in the task bar
        # so it plays nice with kdesk-blur
        self.set_property('skip-taskbar-hint', True)

        self._grid = Gtk.Grid()

        # Create top bar
        self._top_bar = TopBar(title=_("Contact Us"),
                               window_width=self.WIDTH,
                               has_buttons=False)
        self._top_bar.set_close_callback(Gtk.main_quit)
        self.set_decorated(True)
        self.set_titlebar(self._top_bar)

        # Create Text view
        self._text = Gtk.TextView()
        self._text.set_editable(True)
        self._text.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self._text.set_size_request(self.WIDTH, -1)

        self._textbuffer = self._text.get_buffer()
        self._textbuffer.set_text(_("Type your feedback here!"))
        self._clear_buffer_handler_id = self._textbuffer.connect(
            "insert-text", self.clear_buffer)

        scrolledwindow = ScrolledWindow()
        scrolledwindow.set_vexpand(True)
        scrolledwindow.set_policy(Gtk.PolicyType.NEVER,
                                  Gtk.PolicyType.AUTOMATIC)
        scrolledwindow.apply_styling_to_widget()
        scrolledwindow.add(self._text)
        scrolledwindow.set_margin_left(2)
        scrolledwindow.set_margin_right(2)
        scrolledwindow.set_margin_top(2)
        scrolledwindow.set_margin_bottom(2)

        # Very hacky way to get a border: create a grey event box
        # which is a little bigger than the widget below
        border = Gtk.EventBox()
        border.get_style_context().add_class("grey")
        border.add(scrolledwindow)
        self._grid.attach(border, 0, 0, 1, 1)
        border.set_margin_left(20)
        border.set_margin_right(20)
        border.set_margin_top(10)
        border.set_margin_bottom(20)

        # Create send button
        self._send_button = KanoButton(_("SEND"))
        self._send_button.set_sensitive(False)
        self._send_button.connect("button_press_event", self.send_feedback)
        self._send_button.pack_and_align()
        self._send_button.align.set_padding(10, 10, 0, 0)

        bottom_background = Gtk.EventBox()
        bottom_background.get_style_context().add_class("grey")
        bottom_background.add(self._send_button.align)

        self._grid.attach(bottom_background, 0, 1, 1, 1)

        self._grid.set_row_spacing(0)
        self.set_main_widget(self._grid)

        # kano-profile stat collection
        try:
            from kano_profile.badges import increment_app_state_variable_with_dialog
            increment_app_state_variable_with_dialog('kano-feedback', 'starts',
                                                     1)
        except Exception:
            pass