def setUp(self):
     self.app = wx.App()
     self.frame = wx.Frame(None)
     self._model = self._create_model()
     self._tree = Tree(
         self.frame,
         ActionRegisterer(AuiManager(self.frame), MenuBar(self.frame),
                          ToolBar(self.frame),
                          ShortcutRegistry(self.frame)))
     images = TreeImageList()
     self._tree._images = images
     self._tree.SetImageList(images)
     self._tree.populate(self._model)
     self._expand_all()
Exemple #2
0
 def setUp(self):
     settings = FakeSettings()
     self.app = wx.App()
     self.frame = wx.Frame(None)
     self.frame.tree = Tree(
         self.frame,
         ActionRegisterer(AuiManager(self.frame), MenuBar(self.frame),
                          ToolBar(self.frame),
                          ShortcutRegistry(self.frame)), settings)
     self.frame.Show()
     self._tags_list = utils.NormalizedDict()
     self._tags_list = {
         "tag-11": [1, 2],
         "tag-02": [3],
         "tag-12": [4, 8, 12],
         "tag-2": [5, 6, 7],
         "tag-3": [9],
         "tag-21": [10, 11, 12],
         "tag-22": [10],
         "tag-1": [14],
         "tag-03": [15],
         "a-01-a2": [1],
         "08-b": [2],
         "3-2-1-tag-2c": [3, 6, 8],
         "8-B-1": [3, 4, 5],
         "2-b": [7, 3],
         "a-1-a3": [8, 9, 10, 11],
         "3-2-03-tag-2a": [12],
         "a-01-a03": [1],
         "b-1-a01": [2],
         "b-01-a01": [15]
     }
     self.model = self._create_model()
     self._tagsdialog = _ViewAllTagsDialog(self.frame, self.model)
Exemple #3
0
    def _init_ui(self):
        # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane())
        ##### self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
        # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane())
        # set up default notebook style
        self._notebook_style = aui.AUI_NB_DEFAULT_STYLE | \
                               aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER
        # TODO self._notebook_theme = 0 (allow to select themes for notebooks)
        # self.notebook = NoteBook(self.splitter, self._application,
        #                         self._notebook_style)
        self.notebook = NoteBook(self, self._application,
                                 self._notebook_style)
        self._mgr.AddPane(self.notebook,
                          aui.AuiPaneInfo().Name("notebook_editors").
                          CenterPane().PaneBorder(False))
        ################ Test
        # self._mgr.AddPane(self.CreateTextCtrl(),
        #                   aui.AuiPaneInfo().Name("text_content").
        #                   CenterPane().Hide().MinimizeButton(True))
        #
        # self._mgr.AddPane(self.CreateHTMLCtrl(),
        #                   aui.AuiPaneInfo().Name("html_content").
        #                   CenterPane().Hide().MinimizeButton(True))
        #
        # self._mgr.AddPane(self.CreateNotebook(),
        #                   aui.AuiPaneInfo().Name("notebook_content").
        #                   CenterPane().PaneBorder(False))
        ####################
        # self._mgr.AddPane(self.CreateSizeReportCtrl(), aui.AuiPaneInfo().
        #                   Name("test1").Caption(
        #     "Pane Caption").Top().MinimizeButton(True))

        mb = MenuBar(self)
        self.toolbar = ToolBar(self)
        self.toolbar.SetMinSize(wx.Size(100, 60))
        # self.SetToolBar(self.toolbar.GetToolBar())
        self._mgr.AddPane(self.toolbar, aui.AuiPaneInfo().Name("maintoolbar").
                          ToolbarPane().Top())
        self.actions = ActionRegisterer(self._mgr, mb, self.toolbar,
                                        ShortcutRegistry(self))
        """
        ##### Test
        tb3 = self.testToolbar()

        self._mgr.AddPane(tb3,
                          aui.AuiPaneInfo().Name("tb3").Caption("Toolbar 3").
                          ToolbarPane().Top().Row(1).Position(1))
        
        ##### End Test
        """
        # Tree is always created here
        self.tree = Tree(self, self.actions, self._application.settings)
        self.tree.SetMinSize(wx.Size(120, 200))
        # TreePlugin will manage showing the Tree
        self.actions.register_actions(ActionInfoCollection(_menudata, self, self.tree))
        ###### File explorer panel is always created here
        self.filemgr = FileExplorer(self, self._controller)
        self.filemgr.SetMinSize(wx.Size(120, 200))

        mb.take_menu_bar_into_use()
        self.CreateStatusBar()
        self.SetIcons(ImageProvider().PROGICONS)
        # tell the manager to "commit" all the changes just made
        self._mgr.Update()
Exemple #4
0
class RideFrame(with_metaclass(classmaker(), wx.Frame, RideEventHandler)):

    def __init__(self, application, controller):
        size = application.settings.get('mainframe size', (1100, 700))
        wx.Frame.__init__(self, parent=None, id = wx.ID_ANY, title='RIDE',
                          pos=application.settings.get('mainframe position', (50, 30)),
                          size=size, style=wx.DEFAULT_FRAME_STYLE | wx.SUNKEN_BORDER)

        # set Left to Right direction (while we don't have localization)
        self.SetLayoutDirection(wx.Layout_LeftToRight)
        # self.SetLayoutDirection(wx.Layout_RightToLeft)

        self._mgr = aui.AuiManager()

        # tell AuiManager to manage this frame
        self._mgr.SetManagedWindow(self)

        # set frame icon
        # self.SetIcon(Icon('widgets/robot.ico')) # Maybe is not needed
        # self.SetMinSize(size)
        self.SetMinSize(wx.Size(400, 300))

        self.ensure_on_screen()
        if application.settings.get('mainframe maximized', False):
            self.Maximize()
        self._application = application
        self._controller = controller
        self.favicon = Icon(os.path.join(os.path.dirname(__file__), "..",
                                         "widgets","robot.ico"),
                            wx.BITMAP_TYPE_ICO, 256, 256)
        self.SetIcon(self.favicon)  #TODO use SetIcons for all sizes
        self._init_ui()
        self._plugin_manager = PluginManager(self.notebook)
        self._review_dialog = None
        self._view_all_tags_dialog = None
         #, self, self.actions,
        # self._application.settings)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_MOVE, self.OnMove)
        self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
        self.Bind(wx.EVT_DIRCTRL_FILEACTIVATED, self.OnOpenFile)
        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnMenuOpenFile)
        self._subscribe_messages()
        wx.CallAfter(self.actions.register_tools)  # DEBUG

    def _subscribe_messages(self):
        for listener, topic in [
            (lambda msg: self.SetStatusText('Saved %s' % msg.path), RideSaved),
            (lambda msg: self.SetStatusText('Saved all files'), RideSaveAll),
            (self._set_label, RideTreeSelection),
            (self._show_validation_error, RideInputValidationError),
            (self._show_modification_prevented_error,
             RideModificationPrevented)
        ]:
            PUBLISHER.subscribe(listener, topic)

    def _set_label(self, message):
        self.SetTitle(self._create_title(message))

    def _create_title(self, message):
        title = 'RIDE'
        if message:
            item = message.item
            title += ' - ' + item.datafile.name
            if not item.is_modifiable():
                title += ' (READ ONLY)'
        return title

    def _show_validation_error(self, message):
        wx.MessageBox(message.message, 'Validation Error', style=wx.ICON_ERROR)

    def _show_modification_prevented_error(self, message):
        wx.MessageBox("\"%s\" is read only" %
                      message.controller.datafile_controller.filename,
                      "Modification prevented",
                      style=wx.ICON_ERROR)

    def _init_ui(self):
        # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane())
        ##### self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
        # self._mgr.AddPane(wx.Panel(self), aui.AuiPaneInfo().CenterPane())
        # set up default notebook style
        self._notebook_style = aui.AUI_NB_DEFAULT_STYLE | \
                               aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER
        # TODO self._notebook_theme = 0 (allow to select themes for notebooks)
        # self.notebook = NoteBook(self.splitter, self._application,
        #                         self._notebook_style)
        self.notebook = NoteBook(self, self._application,
                                 self._notebook_style)
        self._mgr.AddPane(self.notebook,
                          aui.AuiPaneInfo().Name("notebook_editors").
                          CenterPane().PaneBorder(False))
        ################ Test
        # self._mgr.AddPane(self.CreateTextCtrl(),
        #                   aui.AuiPaneInfo().Name("text_content").
        #                   CenterPane().Hide().MinimizeButton(True))
        #
        # self._mgr.AddPane(self.CreateHTMLCtrl(),
        #                   aui.AuiPaneInfo().Name("html_content").
        #                   CenterPane().Hide().MinimizeButton(True))
        #
        # self._mgr.AddPane(self.CreateNotebook(),
        #                   aui.AuiPaneInfo().Name("notebook_content").
        #                   CenterPane().PaneBorder(False))
        ####################
        # self._mgr.AddPane(self.CreateSizeReportCtrl(), aui.AuiPaneInfo().
        #                   Name("test1").Caption(
        #     "Pane Caption").Top().MinimizeButton(True))

        mb = MenuBar(self)
        self.toolbar = ToolBar(self)
        self.toolbar.SetMinSize(wx.Size(100, 60))
        # self.SetToolBar(self.toolbar.GetToolBar())
        self._mgr.AddPane(self.toolbar, aui.AuiPaneInfo().Name("maintoolbar").
                          ToolbarPane().Top())
        self.actions = ActionRegisterer(self._mgr, mb, self.toolbar,
                                        ShortcutRegistry(self))
        """
        ##### Test
        tb3 = self.testToolbar()

        self._mgr.AddPane(tb3,
                          aui.AuiPaneInfo().Name("tb3").Caption("Toolbar 3").
                          ToolbarPane().Top().Row(1).Position(1))
        
        ##### End Test
        """
        # Tree is always created here
        self.tree = Tree(self, self.actions, self._application.settings)
        self.tree.SetMinSize(wx.Size(120, 200))
        # TreePlugin will manage showing the Tree
        self.actions.register_actions(ActionInfoCollection(_menudata, self, self.tree))
        ###### File explorer panel is always created here
        self.filemgr = FileExplorer(self, self._controller)
        self.filemgr.SetMinSize(wx.Size(120, 200))

        mb.take_menu_bar_into_use()
        self.CreateStatusBar()
        self.SetIcons(ImageProvider().PROGICONS)
        # tell the manager to "commit" all the changes just made
        self._mgr.Update()

    def testToolbar(self):

        #### More testing
        prepend_items, append_items = [], []
        item = aui.AuiToolBarItem()

        item.SetKind(wx.ITEM_SEPARATOR)
        append_items.append(item)

        item = aui.AuiToolBarItem()
        item.SetKind(wx.ITEM_NORMAL)
        item.SetId(ID_CustomizeToolbar)
        item.SetLabel("Customize...")
        append_items.append(item)

        tb3 = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize,
                             agwStyle=aui.AUI_TB_DEFAULT_STYLE | aui.AUI_TB_OVERFLOW)
        tb3.SetToolBitmapSize(wx.Size(16, 16))
        tb3_bmp1 = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER,
                                            wx.Size(16, 16))
        tb3.AddSimpleTool(ID_SampleItem + 16, "Check 1", tb3_bmp1, "Check 1",
                          aui.ITEM_CHECK)
        tb3.AddSimpleTool(ID_SampleItem + 17, "Check 2", tb3_bmp1, "Check 2",
                          aui.ITEM_CHECK)
        tb3.AddSimpleTool(ID_SampleItem + 18, "Check 3", tb3_bmp1, "Check 3",
                          aui.ITEM_CHECK)
        tb3.AddSimpleTool(ID_SampleItem + 19, "Check 4", tb3_bmp1, "Check 4",
                          aui.ITEM_CHECK)
        tb3.AddSeparator()
        tb3.AddSimpleTool(ID_SampleItem + 20, "Radio 1", tb3_bmp1, "Radio 1",
                          aui.ITEM_RADIO)
        tb3.AddSimpleTool(ID_SampleItem + 21, "Radio 2", tb3_bmp1, "Radio 2",
                          aui.ITEM_RADIO)
        tb3.AddSimpleTool(ID_SampleItem + 22, "Radio 3", tb3_bmp1, "Radio 3",
                          aui.ITEM_RADIO)
        tb3.AddSeparator()
        tb3.AddSimpleTool(ID_SampleItem + 23, "Radio 1 (Group 2)", tb3_bmp1,
                          "Radio 1 (Group 2)", aui.ITEM_RADIO)
        tb3.AddSimpleTool(ID_SampleItem + 24, "Radio 2 (Group 2)", tb3_bmp1,
                          "Radio 2 (Group 2)", aui.ITEM_RADIO)
        tb3.AddSimpleTool(ID_SampleItem + 25, "Radio 3 (Group 2)", tb3_bmp1,
                          "Radio 3 (Group 2)", aui.ITEM_RADIO)

        tb3.SetCustomOverflowItems(prepend_items, append_items)
        tb3.Realize()
        return tb3

    def get_selected_datafile(self):
        return self.tree.get_selected_datafile()

    def get_selected_datafile_controller(self):
        return self.tree.get_selected_datafile_controller()

    def OnClose(self, event):
        if self._allowed_to_exit():
            perspective = self._mgr.SavePerspective()
            self._application.settings.set('AUI Perspective', perspective)
            PUBLISHER.unsubscribe(self._set_label, RideTreeSelection)
            RideClosing().publish()
            # deinitialize the frame manager
            self._mgr.UnInit()
            self.Destroy()
        else:
            wx.CloseEvent.Veto(event)

    def OnSize(self, event):
        if not self.IsMaximized():
            self._application.settings['mainframe maximized'] = False
            self._application.settings['mainframe size'] = self.DoGetSize()
        event.Skip()

    def OnMove(self, event):
        # When the window is Iconized, a move event is also raised, but we
        # don't want to update the position in the settings file
        if not self.IsIconized() and not self.IsMaximized():
            self._application.settings['mainframe position'] =\
                self.DoGetPosition()
        event.Skip()

    def OnMaximize(self, event):
        self._application.settings['mainframe maximized'] = True
        event.Skip()

    def OnReleasenotes(self, event):
        pass

    def _allowed_to_exit(self):
        if self.has_unsaved_changes():
            ret = wx.MessageBox("There are unsaved modifications.\n"
                                "Do you want to save your changes before "
                                "exiting?", "Warning",
                                wx.ICON_WARNING | wx.CANCEL | wx.YES_NO)
            if ret == wx.CANCEL:
                return False
            if ret == wx.YES:
                self.save()
        return True

    def has_unsaved_changes(self):
        return self._controller.is_dirty()

    def OnNewProject(self, event):
        if not self.check_unsaved_modifications():
            return
        NewProjectDialog(self._controller).execute()
        self._populate_tree()

    def _populate_tree(self):
        self.tree.populate(self._controller)
        self.filemgr.update_tree()

    def OnOpenFile(self, event):
        if not self.filemgr:
            return
        # EVT_DIRCTRL_FILEACTIVATED
        from os.path import splitext
        robottypes = self._application.settings.get('robot types', ['robot',
                                                                    'resource'
                                                                    'txt',
                                                                    'tsv',
                                                                    'html'])
        path = self.filemgr.GetFilePath()
        ext = ''
        if len(path) > 0:
            ext = splitext(path)
            ext = ext[1].replace('.', '')
            # print("DEBUG: path %s ext %s" % (path, ext))
        if len(ext) > 0 and ext in robottypes:
            if not self.check_unsaved_modifications():
                return
            if self.open_suite(path):
                return
        from robotide.editor import customsourceeditor
        customsourceeditor.main(path)

    def OnMenuOpenFile(self, event):
        if not self.filemgr:
            return
        # TODO: Use widgets/popupmenu tools
        path = self.filemgr.GetFilePath()
        if len(path) > 0:
            self.OnOpenFile(event)
        else:
            path = self.filemgr.GetPath()
            if not self.check_unsaved_modifications():
                return
            self.open_suite(path)  # It is a directory, do not edit
        event.Skip()

    def OnOpenTestSuite(self, event):
        if not self.check_unsaved_modifications():
            return
        path = RobotFilePathDialog(
            self, self._controller, self._application.settings).execute()
        if path:
            if self.open_suite(path):
                return
            from robotide.editor import customsourceeditor
            customsourceeditor.main(path)

    def check_unsaved_modifications(self):
        if self.has_unsaved_changes():
            ret = wx.MessageBox("There are unsaved modifications.\n"
                                "Do you want to proceed without saving?",
                                "Warning", wx.ICON_WARNING | wx.YES_NO)
            return ret == wx.YES
        return True

    def open_suite(self, path):
        self._controller.update_default_dir(path)
        try:
            err = self._controller.load_datafile(path, LoadProgressObserver(self))
        finally:
            if isinstance(err, UserWarning):
                # raise err  # Just leave message in Parser Log
                return False
        self._populate_tree()
        return True

    def refresh_datafile(self, item, event):
        self.tree.refresh_datafile(item, event)
        if self.filemgr:
            self.filemgr.ReCreateTree()

    def OnOpenDirectory(self, event):
        if self.check_unsaved_modifications():
            path = wx.DirSelector(message="Choose a directory containing Robot"
                                          " files",
                                  default_path=self._controller.default_dir)
            if path:
                self.open_suite(path)

    def OnSave(self, event):
        self.save()

    def OnSaveAll(self, event):
        self.save_all()

    def save_all(self):
        self._show_dialog_for_files_without_format()
        self._controller.execute(SaveAll())

    def save(self, controller=None):
        if controller is None:
            controller = self.get_selected_datafile_controller()
        if controller is not None:
            if not controller.has_format():
                self._show_dialog_for_files_without_format(controller)
            else:
                controller.execute(SaveFile())

    def _show_dialog_for_files_without_format(self, controller=None):
        files_without_format = self._controller.get_files_without_format(
            controller)
        for f in files_without_format:
            self._show_format_dialog_for(f)

    def _show_format_dialog_for(self, file_controller_without_format):
        InitFileFormatDialog(file_controller_without_format).execute()

    def OnExit(self, event):
        self.Close()

    def OnManagePlugins(self, event):
        self._plugin_manager.show(self._application.get_plugins())

    def OnViewAllTags(self, event):
        if self._view_all_tags_dialog is None:
            self._view_all_tags_dialog = ViewAllTagsDialog(self._controller, self)
        self._view_all_tags_dialog.show_dialog()

    def OnSearchUnusedKeywords(self, event):
        if self._review_dialog is None:
            self._review_dialog = ReviewDialog(self._controller, self)
        self._review_dialog.show_dialog()

    def OnPreferences(self, event):
        dlg = PreferenceEditor(self, "RIDE - Preferences",
                               self._application.preferences, style='tree')
        # I would prefer that this not be modal, but making it non-
        # modal opens up a can of worms. We don't want to have to deal
        # with settings getting changed out from under us while the
        # dialog is open.
        dlg.ShowModal()
        dlg.Destroy()

    def OnAbout(self, event):
        dlg = AboutDialog()
        dlg.ShowModal()
        dlg.Destroy()

    def OnShortcutkeys(self, event):
        dialog = ShortcutKeysDialog()
        dialog.Show()

    def OnReportaProblem(self, event):
        wx.LaunchDefaultBrowser("https://github.com/robotframework/RIDE/issues"
                                "?utf8=%E2%9C%93&q=is%3Aissue+%22search"
                                "%20your%20problem%22"
                                )

    def OnUserGuide(self, event):
        wx.LaunchDefaultBrowser("http://robotframework.org/robotframework/"
                                "#user-guide")

    def OnWiki(self, event):
        wx.LaunchDefaultBrowser("https://github.com/robotframework/RIDE/wiki")

    def _has_data(self):
        return self._controller.data is not None

    def _refresh(self):
        self._controller.update_namespace()

    # This code is copied from http://wiki.wxpython.org/EnsureFrameIsOnScreen,
    # and adapted to fit our code style.
    def ensure_on_screen(self):
        try:
            display_id = wx.Display.GetFromWindow(self)
        except NotImplementedError:
            display_id = 0
        if display_id == -1:
            display_id = 0
        geometry = wx.Display(display_id).GetGeometry()
        position = self.GetPosition()
        if position.x < geometry.x:
            position.x = geometry.x
        if position.y < geometry.y:
            position.y = geometry.y
        size = self.GetSize()
        if size.width > geometry.width:
            size.width = geometry.width
            position.x = geometry.x
        elif position.x + size.width > geometry.x + geometry.width:
            position.x = geometry.x + geometry.width - size.width
        if size.height > geometry.height:
            size.height = geometry.height
            position.y = geometry.y
        elif position.y + size.height > geometry.y + geometry.height:
            position.y = geometry.y + geometry.height - size.height
        self.SetPosition(position)
        self.SetSize(size)

    # DEBUG just some testing
    def CreateSizeReportCtrl(self, width=80, height=80):

        ctrl = SizeReportCtrl(self, -1, wx.DefaultPosition, wx.Size(width, height), self._mgr)
        return ctrl
class _BaseSuiteTreeTest(unittest.TestCase):
    def setUp(self):
        self.app = wx.App()
        self.frame = wx.Frame(None)
        self._model = self._create_model()
        self._tree = Tree(
            self.frame,
            ActionRegisterer(AuiManager(self.frame), MenuBar(self.frame),
                             ToolBar(self.frame),
                             ShortcutRegistry(self.frame)))
        images = TreeImageList()
        self._tree._images = images
        self._tree.SetImageList(images)
        self._tree.populate(self._model)
        self._expand_all()

    def tearDown(self):
        PUBLISHER.unsubscribe_all()
        wx.CallAfter(self.frame.Close)
        wx.CallAfter(self.app.ExitMainLoop)
        self.app.MainLoop()  # With this here, there is no Segmentation fault
        self.app = None

    def _create_model(self):
        suite = self._create_directory_suite('/top_suite')
        suite.children = [
            self._create_file_suite('sub_suite_%d.txt' % i) for i in range(3)
        ]
        res = ResourceFile()
        res.source = 'resource.txt'
        res.keyword_table.keywords.append(UserKeyword(res, 'Resource Keyword'))
        library_manager = LibraryManager(':memory:')
        library_manager.create_database()
        model = Project(Namespace(FakeSettings()),
                        library_manager=library_manager)
        model._controller = TestDataDirectoryController(suite)
        rfc = ResourceFileController(res, project=model)
        model.resources.append(rfc)
        model.insert_into_suite_structure(rfc)
        return model

    def _create_directory_suite(self, source):
        return self._create_suite(TestDataDirectory, source, is_dir=True)

    def _create_file_suite(self, source):
        suite = self._create_suite(TestCaseFile, source)
        suite.testcase_table.tests = [
            TestCase(suite, '%s Fake Test %d' % (suite.name, i))
            for i in range(5)
        ]
        return suite

    def _create_suite(self, suite_class, source, is_dir=False):
        suite = suite_class()
        suite.source = source
        if is_dir:
            suite.directory = source
        suite.keyword_table.keywords = [
            UserKeyword(suite.keyword_table, '%s Fake UK %d' % (suite.name, i))
            for i in range(5)
        ]
        return suite

    def _expand_all(self):
        for node in self._tree._datafile_nodes[1:]:
            self._tree._expand_and_render_children(node)

    def _get_selected_label(self):
        return self._tree.GetItemText(self._tree.GetSelection())

    def _get_node(self, label):
        node = self._tree._controller.find_node_with_label(
            self._tree._root, label)
        return node or self._tree._controller.find_node_with_label(
            self._tree._root, '*' + label)

    def _select_node(self, label):
        self._tree.SelectItem(self._get_node(label))