diff --git a/gajim/gtk/assistant.py b/gajim/gtk/assistant.py
index 02f32439a6c691e71c4e9662eabcee10b92623ae..d4a1ad8d69994bb128057093846426d43da07a1e 100644
--- a/gajim/gtk/assistant.py
+++ b/gajim/gtk/assistant.py
@@ -67,6 +67,7 @@ def show_all(self):
         page_name = self._ui.stack.get_visible_child_name()
         buttons = self._button_visible_func(self, page_name)
         self._set_buttons_visible(buttons)
+        self.update_page_complete()
         self.emit('page-changed', page_name)
         Gtk.ApplicationWindow.show_all(self)
 
@@ -74,20 +75,30 @@ def _on_key_press_event(self, _widget, event):
         if event.keyval == Gdk.KEY_Escape:
             self.destroy()
 
+    def update_page_complete(self):
+        page_widget = self._ui.stack.get_visible_child()
+        for button, complete in self._buttons.values():
+            if complete:
+                button.set_sensitive(page_widget.complete)
+
+    def update_title(self):
+        self.set_title(self._ui.stack.get_visible_child().title)
+
     def set_button_visible_func(self, func):
         self._button_visible_func = func
 
     def set_default_button(self, button_name):
-        self._buttons[button_name].grab_default()
+        button, _ = self._buttons[button_name]
+        button.grab_default()
 
-    def add_button(self, name, label, css_class=None):
+    def add_button(self, name, label, css_class=None, complete=False):
         button = Gtk.Button(label=label,
                             can_default=True,
                             no_show_all=True)
         button.connect('clicked', self.__on_button_clicked)
         if css_class is not None:
             button.get_style_context().add_class(css_class)
-        self._buttons[name] = button
+        self._buttons[name] = (button, complete)
         self._ui.action_area.pack_end(button, False, False, 0)
 
     def add_pages(self, pages):
@@ -121,21 +132,24 @@ def get_page(self, name):
         return self._pages[name]
 
     def _set_buttons_visible(self, buttons):
-        for button in self._buttons.values():
+        for button, _ in self._buttons.values():
             button.hide()
 
         if buttons is None:
             return
 
         for button_name in buttons:
-            self._buttons[button_name].show()
+            button, _ = self._buttons[button_name]
+            button.show()
 
     def _on_visible_child_name(self, stack, _param):
-        self.set_title(stack.get_visible_child().title)
+        self.update_title()
+        self.update_page_complete()
         self.emit('page-changed', stack.get_visible_child_name())
 
     def __on_button_clicked(self, button):
-        for button_name, button_ in self._buttons.items():
+        for button_name, button_data in self._buttons.items():
+            button_ = button_data[0]
             if button_ == button:
                 self.emit('button-clicked', button_name)
                 return
@@ -146,12 +160,18 @@ def __on_destroy(self, *args):
 
 
 class Page(Gtk.Box):
-    def __init__(self, icon_name, icon_css_class):
-        super().__init__(orientation=Gtk.Orientation.VERTICAL)
+    def __init__(self):
+        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
         self.set_spacing(18)
         self.set_valign(Gtk.Align.CENTER)
 
         self.title = ''
+        self.complete = True
+
+
+class DefaultPage(Page):
+    def __init__(self, icon_name, icon_css_class):
+        Page.__init__(self)
 
         self._heading = Gtk.Label()
         self._heading.get_style_context().add_class('large-header')
@@ -184,27 +204,23 @@ def set_title(self, title):
         self.title = title
 
 
-class ErrorPage(Page):
+class ErrorPage(DefaultPage):
     def __init__(self):
-        Page.__init__(self,
-                      icon_name='dialog-error-symbolic',
-                      icon_css_class='error-color')
+        DefaultPage.__init__(self,
+                             icon_name='dialog-error-symbolic',
+                             icon_css_class='error-color')
 
 
-class SuccessPage(Page):
+class SuccessPage(DefaultPage):
     def __init__(self):
-        Page.__init__(self,
-                      icon_name='object-select-symbolic',
-                      icon_css_class='success-color')
+        DefaultPage.__init__(self,
+                             icon_name='object-select-symbolic',
+                             icon_css_class='success-color')
 
 
-class ProgressPage(Gtk.Box):
+class ProgressPage(Page):
     def __init__(self):
-        super().__init__(orientation=Gtk.Orientation.VERTICAL)
-        self.set_spacing(18)
-        self.set_valign(Gtk.Align.CENTER)
-
-        self.title = ''
+        Page.__init__(self)
 
         self._label = Gtk.Label()
         self._label.set_max_width_chars(50)
diff --git a/test/gtk/assistant.py b/test/gtk/assistant.py
index c7378d063e59f39beba6b636e45f263f848aa01d..a052bbed0687a91645fff0319b86a54bc5b9b92f 100644
--- a/test/gtk/assistant.py
+++ b/test/gtk/assistant.py
@@ -5,6 +5,7 @@
 from gajim.common.const import CSSPriority
 
 from gajim.gtk.assistant import Assistant
+from gajim.gtk.assistant import Page
 
 from test.gtk import util
 util.load_style('gajim.css', CSSPriority.APPLICATION)
@@ -30,7 +31,7 @@ def __init__(self):
         success.set_heading('Success Heading')
         success.set_text('This is the success text')
 
-        self.add_button('forward', 'Forward', 'suggested-action')
+        self.add_button('forward', 'Forward', 'suggested-action', complete=True)
         self.add_button('close', 'Close', 'destructive-action')
         self.add_button('back', 'Back')
 
@@ -93,14 +94,13 @@ def _on_page_changed(self, _assistant, page_name):
             self.set_default_button('back')
 
 
-class Start(Gtk.Box):
+class Start(Page):
+    def __init__(self):
+        Page.__init__(self)
 
-    title = 'Start'
+        self.title = 'Start'
+        self.complete = False
 
-    def __init__(self):
-        super().__init__(orientation=Gtk.Orientation.VERTICAL)
-        self.set_spacing(18)
-        self.set_valign(Gtk.Align.CENTER)
         heading = Gtk.Label(label='Test Assistant')
         heading.get_style_context().add_class('large-header')
 
@@ -111,21 +111,22 @@ def __init__(self):
         label1.set_justify(Gtk.Justification.CENTER)
         label1.set_margin_bottom(24)
 
-        label2 = Gtk.Label(label='This is label 2 with some more text')
-        label2.set_max_width_chars(50)
-        label2.set_line_wrap(True)
-        label2.set_halign(Gtk.Align.CENTER)
-        label2.set_justify(Gtk.Justification.CENTER)
+        entry = Gtk.Entry(activates_default=True)
+        entry.connect('changed', self._on_changed)
 
         self._server = Gtk.CheckButton.new_with_mnemonic('A fancy checkbox')
         self._server.set_halign(Gtk.Align.CENTER)
 
         self.pack_start(heading, False, True, 0)
         self.pack_start(label1, False, True, 0)
-        self.pack_start(label2, False, True, 0)
+        self.pack_start(entry, False, True, 0)
         self.pack_start(self._server, False, True, 0)
         self.show_all()
 
+    def _on_changed(self, entry):
+        self.complete = bool(entry.get_text())
+        self.get_toplevel().update_page_complete()
+
 
 win = TestAssistant()
 win.connect('destroy', Gtk.main_quit)