Ejemplo n.º 1
0
    def setProject(self, project, localRoot=''):
        if not isinstance(project, pavlovia.PavloviaProject):
            project = pavlovia.getCurrentSession().getProject(project)
        if project is None:
            return  # we're done
        self.project = project

        if not self.noTitle:
            # use the id (namespace/name) but give space around /
            self.title.SetLabel(project.id.replace("/", " / "))

        # url
        self.url.SetLabel(self.project.web_url)
        self.url.SetURL(self.project.web_url)

        # public / private
        if hasattr(project.attributes,
                   'description') and project.attributes['description']:
            self.description.SetLabel(project.attributes['description'])
        else:
            self.description.SetLabel('')
        if not hasattr(project, 'visibility'):
            visib = _translate("User not logged in!")
        elif project.visibility in ['public', 'internal']:
            visib = "Public"
        else:
            visib = "Private"
        self.visibility.SetLabel(_translate("Visibility: {}").format(visib))

        # do we have a local location?
        localFolder = project.localRoot
        if not localFolder:
            localFolder = _translate("<not yet synced>")
        self.localFolderCtrl.SetLabel(
            _translate("Local root: {}").format(localFolder))

        # Check permissions: login, fork or sync
        perms = project.permissions

        # we've got the permissions value so use it
        if not pavlovia.getCurrentSession().user:
            self.syncButton.SetLabel(_translate('Log in to sync...'))
        elif not perms or perms < pavlovia.permissions['developer']:
            self.syncButton.SetLabel(_translate('Fork + sync...'))
        else:
            self.syncButton.SetLabel(_translate('Sync...'))
        self.syncButton.Enable(True)  # now we have a project we should enable

        while None in project.tags:
            project.tags.remove(None)
        self.tags.SetLabel(_translate("Tags:") + " " + ", ".join(project.tags))
        # call onResize to get correct wrapping of description box and title
        self.onResize()
Ejemplo n.º 2
0
    def setProject(self, project, localRoot=''):
        if not isinstance(project, pavlovia.PavloviaProject):
            project = pavlovia.getCurrentSession().getProject(project)
        if project is None:
            return  # we're done
        self.project = project

        if not self.noTitle:
            # use the id (namespace/name) but give space around /
            self.title.SetLabel(project.id.replace("/", " / "))

        # url
        self.url.SetLabel(self.project.web_url)
        self.url.SetURL(self.project.web_url)

        # public / private
        if hasattr(project.attributes, 'description') and project.attributes['description']:
            self.description.SetLabel(project.attributes['description'])
        else:
            self.description.SetLabel('')
        if not hasattr(project, 'visibility'):
            visib = _translate("User not logged in!")
        elif project.visibility in ['public', 'internal']:
            visib = "Public"
        else:
            visib = "Private"
        self.visibility.SetLabel(_translate("Visibility: {}").format(visib))

        # do we have a local location?
        localFolder = project.localRoot
        if not localFolder:
            localFolder = _translate("<not yet synced>")
        self.localFolderCtrl.SetLabel(_translate("Local root: {}").format(localFolder))

        # Check permissions: login, fork or sync
        perms = project.permissions

        # we've got the permissions value so use it
        if not pavlovia.getCurrentSession().user:
            self.syncButton.SetLabel(_translate('Log in to sync...'))
        elif not perms or perms < pavlovia.permissions['developer']:
            self.syncButton.SetLabel(_translate('Fork + sync...'))
        else:
            self.syncButton.SetLabel(_translate('Sync...'))
        self.syncButton.Enable(True)  # now we have a project we should enable

        while None in project.tags:
            project.tags.remove(None)
        self.tags.SetLabel(_translate("Tags:") + " " + ", ".join(project.tags))
        # call onResize to get correct wrapping of description box and title
        self.onResize()
Ejemplo n.º 3
0
    def __init__(self, project, *args, **kwargs):
        wx.Dialog.__init__(self, *args, **kwargs)

        existingName = project.name
        session = pavlovia.getCurrentSession()
        groups = [session.user.username]
        groups.extend(session.listUserGroups())
        msg = wx.StaticText(self, label="Where shall we fork to?")
        groupLbl = wx.StaticText(self, label="Group:")
        self.groupField = wx.Choice(self, choices=groups)
        nameLbl = wx.StaticText(self, label="Project name:")
        self.nameField = wx.TextCtrl(self, value=project.name)

        fieldsSizer = wx.FlexGridSizer(cols=2, rows=2, vgap=5, hgap=5)
        fieldsSizer.AddMany([groupLbl, self.groupField,
                             nameLbl, self.nameField])

        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonSizer.Add(wx.Button(self, id=wx.ID_OK, label="OK"))
        buttonSizer.Add(wx.Button(self, id=wx.ID_CANCEL, label="Cancel"))

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(msg, 1, wx.ALL, 5)
        mainSizer.Add(fieldsSizer, 1, wx.ALL, 5)
        mainSizer.Add(buttonSizer, 1, wx.ALL | wx.ALIGN_RIGHT, 5)

        self.SetSizerAndFit(mainSizer)
        self.Layout()
Ejemplo n.º 4
0
    def __init__(self, project, *args, **kwargs):
        wx.Dialog.__init__(self, *args, **kwargs)

        existingName = project.name
        session = pavlovia.getCurrentSession()
        groups = [session.user.username]
        groups.extend(session.listUserGroups())
        msg = wx.StaticText(self, label="Where shall we fork to?")
        groupLbl = wx.StaticText(self, label="Group:")
        self.groupField = wx.Choice(self, choices=groups)
        nameLbl = wx.StaticText(self, label="Project name:")
        self.nameField = wx.TextCtrl(self, value=project.name)

        fieldsSizer = wx.FlexGridSizer(cols=2, rows=2, vgap=5, hgap=5)
        fieldsSizer.AddMany(
            [groupLbl, self.groupField, nameLbl, self.nameField])

        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        buttonSizer.Add(wx.Button(self, id=wx.ID_OK, label="OK"))
        buttonSizer.Add(wx.Button(self, id=wx.ID_CANCEL, label="Cancel"))

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        mainSizer.Add(msg, 1, wx.ALL, 5)
        mainSizer.Add(fieldsSizer, 1, wx.ALL, 5)
        mainSizer.Add(buttonSizer, 1, wx.ALL | wx.ALIGN_RIGHT, 5)

        self.SetSizerAndFit(mainSizer)
        self.Layout()
Ejemplo n.º 5
0
    def onSearch(self, evt=None):
        opts = self.getSearchOptions()

        searchStr = self.searchCtrl.GetValue()
        newSearch = (searchStr != self.lastSearchStr)
        self.lastSearchStr = newSearch

        session = pavlovia.getCurrentSession()
        # search own
        if newSearch:
            try:
                self.lastSearchOwn = session.gitlab.projects.list(
                    owned=True, search=searchStr)
            except requests.exceptions.ConnectionError:
                print("Failed to establish a new connection: No internet?")
                return None

        # search my groups
        if opts['inclGroup'] and (newSearch or self.lastSearchGp is None):
            # group projects: owned=False, membership=True
            self.lastSearchGp = session.gitlab.projects.list(owned=False,
                                                             membership=True,
                                                             search=searchStr)
        elif not opts[
                'inclGroup']:  # set to None (to indicate non-search not simply empty result)
            self.lastSearchGp = None
        elif opts['inclGroup'] and not newSearch:
            pass  # we have last search and we need it so do nothing
        else:
            print(
                "ERROR: During Pavlovia search we found opts['inclGroup']={}, newSearch={}"
                .format(opts['inclGroup'], newSearch))

        # search public
        if opts['inclPublic'] and (newSearch or self.lastSearchPub is None):
            self.lastSearchPub = session.gitlab.projects.list(owned=False,
                                                              membership=False,
                                                              search=searchStr)
        elif not opts[
                'inclPublic']:  # set to None (to indicate non-search not simply empty result)
            self.lastSearchPub = None
        elif opts['inclPublic'] and not newSearch:
            pass  # we have last search and we need it so do nothing
        else:
            print(
                "ERROR: During Pavlovia search we found opts['inclPublic']={}, newSearch={}"
                .format(opts['inclPublic'], newSearch))

        projs = copy.copy(self.lastSearchOwn)
        if opts['inclGroup']:
            projs.extend(self.lastSearchGp)
        if opts['inclPublic']:
            projs.extend(self.lastSearchPub)

        projs = getUniqueByID(projs)
        projs = [pavlovia.PavloviaProject(proj) for proj in projs if proj.id]

        self.searchResults.setContents(projs)
        self.searchResults.Update()
        self.Layout()
Ejemplo n.º 6
0
    def __init__(self,
                 parent,
                 user=None,
                 loginOnly=False,
                 logoutOnly=False,
                 style=style,
                 *args,
                 **kwargs):
        # create the dialog
        wx.Dialog.__init__(self, parent, style=style, *args, **kwargs)
        # create browser window for authentication
        self.browser = wx.html2.WebView.New(self)
        self.loginOnly = loginOnly
        self.logoutOnly = logoutOnly
        self.tokenInfo = {}

        # do layout
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.browser, 1, wx.EXPAND, 10)
        self.SetSizer(sizer)
        if loginOnly:
            self.SetSize((600, 600))
        else:
            self.SetSize((700, 600))
        self.CenterOnParent()

        # check there is a user (or log them in)
        if not user:
            self.user = pavlovia.getCurrentSession().user
        if not user:
            self.login()
        if not user:
            return None
Ejemplo n.º 7
0
    def __init__(self, parent, user=None, loginOnly=False, logoutOnly=False,
                 style=style, *args, **kwargs):
        # create the dialog
        wx.Dialog.__init__(self, parent, style=style, *args, **kwargs)
        # create browser window for authentication
        self.browser = wx.html2.WebView.New(self)
        self.loginOnly = loginOnly
        self.logoutOnly = logoutOnly
        self.tokenInfo = {}

        # do layout
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.browser, 1, wx.EXPAND, 10)
        self.SetSizer(sizer)
        if loginOnly:
            self.SetSize((600, 600))
        else:
            self.SetSize((700, 600))
        self.CenterOnParent()

        # check there is a user (or log them in)
        if not user:
            self.user = pavlovia.getCurrentSession().user
        if not user:
            self.login()
        if not user:
            return None
Ejemplo n.º 8
0
    def setUser(self, user):
        if user == PavloviaMenu.currentUser:
            return  # nothing to do here. Move along please.
        PavloviaMenu.currentUser = user
        PavloviaMenu.appData['pavloviaUser'] = user
        if user in pavlovia.knownUsers:
            token = pavlovia.knownUsers[user]['token']
            try:
                pavlovia.getCurrentSession().setToken(token)
            except requests.exceptions.ConnectionError:
                logging.warning("Tried to log in to Pavlovia but no network "
                                "connection")
                return
        else:
            self.onLogInPavlovia()

        if self.searchDlg:
            self.searchDlg.updateUserProjs()
Ejemplo n.º 9
0
    def setUser(self, user):
        if user == PavloviaMenu.currentUser:
            return  # nothing to do here. Move along please.
        PavloviaMenu.currentUser = user
        PavloviaMenu.appData['pavloviaUser'] = user
        if user in pavlovia.knownUsers:
            token = pavlovia.knownUsers[user]['token']
            try:
                pavlovia.getCurrentSession().setToken(token)
            except requests.exceptions.ConnectionError:
                logging.warning("Tried to log in to Pavlovia but no network "
                                "connection")
                return
        else:
            self.onLogInPavlovia()

        if self.searchDlg:
            self.searchDlg.updateUserProjs()
Ejemplo n.º 10
0
    def onSearch(self, evt=None):
        opts = self.getSearchOptions()

        searchStr = self.searchCtrl.GetValue()
        newSearch = (searchStr!=self.lastSearchStr)
        self.lastSearchStr = newSearch

        session = pavlovia.getCurrentSession()
        # search own
        if newSearch:
            try:
                self.lastSearchOwn = session.gitlab.projects.list(owned=True, search=searchStr)
            except requests.exceptions.ConnectionError:
                print("Failed to establish a new connection: No internet?")
                return None

        # search my groups
        if opts['inclGroup'] and (newSearch or self.lastSearchGp is None):
            # group projects: owned=False, membership=True
            self.lastSearchGp = session.gitlab.projects.list(
                owned=False, membership=True, search=searchStr)
        elif not opts['inclGroup']:  # set to None (to indicate non-search not simply empty result)
            self.lastSearchGp = None
        elif opts['inclGroup'] and not newSearch:
            pass  # we have last search and we need it so do nothing
        else:
            print("ERROR: During Pavlovia search we found opts['inclGroup']={}, newSearch={}"
                  .format(opts['inclGroup'], newSearch))

        # search public
        if opts['inclPublic'] and (newSearch or self.lastSearchPub is None):
            self.lastSearchPub = session.gitlab.projects.list(owned=False, membership=False,
                                                              search=searchStr)
        elif not opts['inclPublic']:  # set to None (to indicate non-search not simply empty result)
            self.lastSearchPub = None
        elif opts['inclPublic'] and not newSearch:
            pass  # we have last search and we need it so do nothing
        else:
            print("ERROR: During Pavlovia search we found opts['inclPublic']={}, newSearch={}"
                  .format(opts['inclPublic'], newSearch))

        projs = copy.copy(self.lastSearchOwn)
        if opts['inclGroup']:
            projs.extend(self.lastSearchGp)
        if opts['inclPublic']:
            projs.extend(self.lastSearchPub)

        projs = getUniqueByID(projs)
        projs = [pavlovia.PavloviaProject(proj) for proj in projs if proj.id]

        self.searchResults.setContents(projs)
        self.searchResults.Update()
        self.Layout()
Ejemplo n.º 11
0
    def onSyncButton(self, event):
        try:
            git
            haveGit = True
        except ImportError:
            haveGit = False
        if not haveGit:
            noGitWarning(parent=self.parent)
            return

        if self.project is None:
            raise AttributeError("User pressed the sync button with no "
                                 "current project existing.")

        # log in first if needed
        if not pavlovia.getCurrentSession().user:
            logInPavlovia(parent=self.parent)
            return

        # fork first if needed
        perms = self.project.permissions
        if not perms or perms < pavlovia.permissions['developer']:
            # specifying the group to fork to has no effect so don't use it
            # dlg = ForkDlg(parent=self.parent, project=self.project)
            # if dlg.ShowModal() == wx.ID_CANCEL:
            #     return
            # else:
            #     newGp = dlg.groupField.GetStringSelection()
            #     newName = dlg.nameField.GetValue()
            fork = self.project.forkTo()  # logged-in user
            self.setProject(fork.id)

        # if project.localRoot doesn't exist, or is empty
        if 'localRoot' not in self.project or not self.project.localRoot:
            # we first need to choose a location for the repository
            newPath = setLocalPath(self, self.project)
            if newPath:
                self.localFolderCtrl.SetLabel(
                    label=_translate("Local root: {}").format(newPath))
            self.project.local = newPath
            self.Layout()
            self.Raise()

        syncPanel = sync.SyncStatusPanel(parent=self, id=wx.ID_ANY)
        self.sizer.Add(syncPanel, border=5,
                       flag=wx.ALL | wx.RIGHT)
        self.sizer.Layout()
        progHandler = sync.ProgressHandler(syncPanel=syncPanel)
        wx.Yield()
        self.project.sync(syncPanel=syncPanel, progressHandler=progHandler)
        syncPanel.Destroy()
        self.sizer.Layout()
        self.parent.Raise()
Ejemplo n.º 12
0
    def onSyncButton(self, event):
        try:
            git
            haveGit = True
        except ImportError:
            haveGit = False
        if not haveGit:
            noGitWarning(parent=self.parent)
            return

        if self.project is None:
            raise AttributeError("User pressed the sync button with no "
                                 "current project existing.")

        # log in first if needed
        if not pavlovia.getCurrentSession().user:
            logInPavlovia(parent=self.parent)
            return

        # fork first if needed
        perms = self.project.permissions
        if not perms or perms < pavlovia.permissions['developer']:
            # specifying the group to fork to has no effect so don't use it
            # dlg = ForkDlg(parent=self.parent, project=self.project)
            # if dlg.ShowModal() == wx.ID_CANCEL:
            #     return
            # else:
            #     newGp = dlg.groupField.GetStringSelection()
            #     newName = dlg.nameField.GetValue()
            fork = self.project.forkTo()  # logged-in user
            self.setProject(fork.id)

        # if project.localRoot doesn't exist, or is empty
        if 'localRoot' not in self.project or not self.project.localRoot:
            # we first need to choose a location for the repository
            newPath = setLocalPath(self, self.project)
            if newPath:
                self.localFolderCtrl.SetLabel(
                    label=_translate("Local root: {}").format(newPath))
            self.project.local = newPath
            self.Layout()
            self.Raise()

        syncPanel = sync.SyncStatusPanel(parent=self, id=wx.ID_ANY)
        self.sizer.Add(syncPanel, border=5, flag=wx.ALL | wx.RIGHT)
        self.sizer.Layout()
        progHandler = sync.ProgressHandler(syncPanel=syncPanel)
        wx.Yield()
        self.project.sync(syncPanel=syncPanel, progressHandler=progHandler)
        syncPanel.Destroy()
        self.sizer.Layout()
        self.parent.Raise()
Ejemplo n.º 13
0
def logInPavlovia(parent, event=None):
    """Opens the built-in browser dialog to login to pavlovia

    Returns
    -------
    None (user closed window without logging on) or a gitlab.User object
    """
    # check known users list
    dlg = PavloviaMiniBrowser(parent=parent, loginOnly=True)
    dlg.ShowModal()  # with loginOnly=True this will EndModal once logged in
    if dlg.tokenInfo:
        token = dlg.tokenInfo['token']
        pavlovia.login(token, rememberMe=True)  # log in to the current pavlovia session
        return pavlovia.getCurrentSession().user
Ejemplo n.º 14
0
def logInPavlovia(parent, event=None):
    """Opens the built-in browser dialog to login to pavlovia

    Returns
    -------
    None (user closed window without logging on) or a gitlab.User object
    """
    # check known users list
    dlg = PavloviaMiniBrowser(parent=parent, loginOnly=True)
    dlg.ShowModal()  # with loginOnly=True this will EndModal once logged in
    if dlg.tokenInfo:
        token = dlg.tokenInfo['token']
        pavlovia.login(token, rememberMe=True)  # log in to the current pavlovia session
        return pavlovia.getCurrentSession().user
Ejemplo n.º 15
0
 def onNew(self, event):
     """Create a new project
     """
     if pavlovia.getCurrentSession().user.username:
         projEditor = ProjectEditor()
         if projEditor.ShowModal() == wx.ID_OK:
             self.parent.project = projEditor.project
             # do a first sync as well
             syncProject(parent=self.parent, project=projEditor.project)
     else:
         infoDlg = dialogs.MessageDialog(parent=None, type='Info',
                                         message=_translate(
                                                 "You need to log in"
                                                 " to create a project"))
         infoDlg.Show()
Ejemplo n.º 16
0
        def onSelectUser(evt):
            # Get user from menu
            id = evt.Id
            menu = evt.EventObject
            user = menu.users[id]
            # Logout
            pavlovia.logout()
            # Log back in as new user
            pavlovia.login(user['username'])
            # Update view
            self.user = pavlovia.getCurrentSession().user
            # Update cache
            prefs.appData['projects']['pavloviaUser'] = user['username']

            self.Layout()  # update the size of the button
            self.Fit()
Ejemplo n.º 17
0
 def onNew(self, event):
     """Create a new project
     """
     # Get session
     session = pavlovia.getCurrentSession()
     # If logged in, create project
     if session.user:
         dlg = sync.CreateDlg(self.parent, user=session.user)
         dlg.ShowModal()
     # Otherwise, prompt user to log in
     else:
         infoDlg = dialogs.MessageDialog(parent=None,
                                         type='Info',
                                         message=_translate(
                                             "You need to log in"
                                             " to create a project"))
         infoDlg.Show()
Ejemplo n.º 18
0
    def submitChanges(self, evt=None):
        session = pavlovia.getCurrentSession()
        if not session.user:
            user = logInPavlovia(parent=self.parent)
        if not session.user:
            return
        # get current values
        name = self.nameBox.GetValue()
        namespace = self.groupBox.GetStringSelection()
        descr = self.descrBox.GetValue()
        visibility = self.publicBox.GetValue()
        # tags need splitting and then
        tagsList = self.tagsBox.GetValue().split(',')
        tags = [thisTag.strip() for thisTag in tagsList]
        localRoot = self.localBox.GetValue()
        if not localRoot:
            localRoot = setLocalPath(self.parent, project=None, path="")

        # then create/update
        if self.isNew:
            project = session.createProject(name=name,
                                            description=descr,
                                            tags=tags,
                                            visibility=visibility,
                                            localRoot=localRoot,
                                            namespace=namespace)
            self.project = project
            self.project._newRemote = True
        else:  # we're changing metadata of an existing project. Don't sync
            self.project.pavlovia.name = name
            self.project.pavlovia.description = descr
            self.project.tags = tags
            self.project.visibility = visibility
            self.project.localRoot = localRoot
            self.project.save()  # pushes changed metadata to gitlab
            self.project._newRemote = False

        self.EndModal(wx.ID_OK)
        pavlovia.knownProjects.save()
        self.project.getRepo(forceRefresh=True)
        self.parent.project = self.project
Ejemplo n.º 19
0
    def onSyncButton(self, event):
        if not pavlovia.haveGit:
            noGitWarning(parent=self.parent)
            return 0

        if self.project is None:
            raise AttributeError("User pressed the sync button with no "
                                 "current project existing.")

        # log in first if needed
        if not pavlovia.getCurrentSession().user:
            logInPavlovia(parent=self.parent)
            return

        # fork first if needed
        perms = self.project.permissions
        if not perms or perms < pavlovia.permissions['developer']:
            # specifying the group to fork to has no effect so don't use it
            # dlg = ForkDlg(parent=self.parent, project=self.project)
            # if dlg.ShowModal() == wx.ID_CANCEL:
            #     return
            # else:
            #     newGp = dlg.groupField.GetStringSelection()
            #     newName = dlg.nameField.GetValue()
            fork = self.project.forkTo()  # logged-in user
            self.setProject(fork.id)

        # if project.localRoot doesn't exist, or is empty
        if 'localRoot' not in self.project or not self.project.localRoot:
            # we first need to choose a location for the repository
            newPath = setLocalPath(self, self.project)
            if newPath:
                self.localFolderCtrl.SetLabel(
                    label=_translate("Local root: {}").format(newPath))
            self.project.local = newPath
            self.Layout()
            self.Raise()

        self.syncPanel.setStatus(_translate("Synchronizing..."))
        self.project.sync(infoStream=self.syncPanel.infoStream)
        self.parent.Raise()
Ejemplo n.º 20
0
    def submitChanges(self, evt=None):
        session = pavlovia.getCurrentSession()
        if not session.user:
            user = logInPavlovia(parent=self.parent)
        if not session.user:
            return
        # get current values
        name = self.nameBox.GetValue()
        namespace = self.groupBox.GetStringSelection()
        descr = self.descrBox.GetValue()
        visibility = self.publicBox.GetValue()
        # tags need splitting and then
        tagsList = self.tagsBox.GetValue().split(',')
        tags = [thisTag.strip() for thisTag in tagsList]
        localRoot = self.localBox.GetValue()
        if not localRoot:
            localRoot = setLocalPath(self.parent, project=None, path="")

        # then create/update
        if self.isNew:
            project = session.createProject(name=name,
                                            description=descr,
                                            tags=tags,
                                            visibility=visibility,
                                            localRoot=localRoot,
                                            namespace=namespace)
            self.project = project
            self.project._newRemote = True
        else:  # we're changing metadata of an existing project. Don't sync
            self.project.pavlovia.name = name
            self.project.pavlovia.description = descr
            self.project.tags = tags
            self.project.visibility = visibility
            self.project.localRoot = localRoot
            self.project.save()  # pushes changed metadata to gitlab
            self.project._newRemote = False

        self.EndModal(wx.ID_OK)
        pavlovia.knownProjects.save()
        self.project.getRepo(forceRefresh=True)
        self.parent.project = self.project
Ejemplo n.º 21
0
    def onSyncButton(self, event):
        if not pavlovia.haveGit:
            noGitWarning(parent=self.parent)
            return 0

        if self.project is None:
            raise AttributeError("User pressed the sync button with no "
                                 "current project existing.")

        # log in first if needed
        if not pavlovia.getCurrentSession().user:
            logInPavlovia(parent=self.parent)
            return

        # fork first if needed
        perms = self.project.permissions
        if not perms or perms < pavlovia.permissions['developer']:
            # specifying the group to fork to has no effect so don't use it
            # dlg = ForkDlg(parent=self.parent, project=self.project)
            # if dlg.ShowModal() == wx.ID_CANCEL:
            #     return
            # else:
            #     newGp = dlg.groupField.GetStringSelection()
            #     newName = dlg.nameField.GetValue()
            fork = self.project.forkTo()  # logged-in user
            self.setProject(fork.id)

        # if project.localRoot doesn't exist, or is empty
        if 'localRoot' not in self.project or not self.project.localRoot:
            # we first need to choose a location for the repository
            newPath = setLocalPath(self, self.project)
            if newPath:
                self.localFolderCtrl.SetLabel(
                    label=_translate("Local root: {}").format(newPath))
            self.project.local = newPath
            self.Layout()
            self.Raise()

        self.syncPanel.setStatus(_translate("Synchronizing..."))
        self.project.sync(infoStream=self.syncPanel.infoStream)
        self.parent.Raise()
Ejemplo n.º 22
0
    def __init__(self, parent=None, id=wx.ID_ANY, style=defStyle,
                 *args, **kwargs):

        wx.Dialog.__init__(self, parent, id,
                           *args, style=style, **kwargs)
        self.SetWindowStyle(wx.STAY_ON_TOP)  # this will be a modal dialog

        panel = wx.Panel(self, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.parent = parent
        pavSession = pavlovia.getCurrentSession()
        if pavSession.user:
            pavSession.gitlab.auth()
            self.user = pavSession.user
        else:
            self.user = logInPavlovia(parent=parent)
            if not self.user:
                return  # they were given a login but cancelled
        if type(self.user) != pavlovia.User:
            self.user = pavlovia.User(gitlabData=self.user)

        # create the controls
        userField = wxhl.HyperLinkCtrl(panel, id=wx.ID_ANY,
                                       label=self.user.url, URL=self.user.url)
        logoutBtn = wx.Button(panel, label="Logout")
        logoutBtn.Bind(wx.EVT_BUTTON, self.onLogout)
        nameLabel = wx.StaticText(panel, id=wx.ID_ANY, label=_translate("Full name:"))
        self.nameField = wx.StaticText(panel, wx.ID_ANY, self.user.name)
        if self.user.avatar:
            userBitmap = wx.Bitmap(self.user.avatar)
        else:
            userBitmap = wx.Bitmap(os.path.join(resources, "user128invisible.png"))
        # self.avatarBtn = wx.Button(panel, wx.ID_ANY, name="Avatar")
        # self.avatarBtn.SetBitmap(userBitmap)
        self.avatarBtn = wx.BitmapButton(panel, wx.ID_ANY,
                                         bitmap=userBitmap, name="Avatar")
        # self.avatarBtn.SetBitmap(userBitmap)

        org = self.user.organization or ""
        orgLabel = wx.StaticText(panel, wx.ID_ANY, _translate("Organization:"))
        self.orgField = wx.StaticText(panel, wx.ID_ANY, org, size=(300, -1))

        bio = self.user.bio or ""
        self.bioLabel = wx.StaticText(panel, wx.ID_ANY, _translate("Bio (250 chrs):"))
        self.bioField = wx.StaticText(panel, wx.ID_ANY, bio,
                                    style=wx.TE_MULTILINE)
        # submit/cancel
        buttonMsg = _translate("OK")
        updateBtn = wx.Button(panel, id=wx.ID_OK, label=buttonMsg)
        updateBtn.Bind(wx.EVT_BUTTON, self.submitChanges)
        # cancelBtn = wx.Button(panel, id=wx.ID_CANCEL, label=_translate("Cancel"))
        # cancelBtn.Bind(wx.EVT_BUTTON, self.onCancel)

        # layout
        userAndLogout = wx.BoxSizer(wx.VERTICAL)
        userAndLogout.Add(userField, 1, wx.ALL | wx.CENTER | wx.ALIGN_CENTER_VERTICAL, 5)
        userAndLogout.Add(logoutBtn, 0, wx.ALL | wx.CENTER | wx.ALIGN_CENTER_VERTICAL , 5)
        topRow = wx.BoxSizer(wx.HORIZONTAL)
        topRow.Add(userAndLogout, 1, wx.ALL | wx.CENTER, 5)
        topRow.Add(self.avatarBtn, 0, wx.ALL | wx.RIGHT, 5)

        fieldsSizer = wx.FlexGridSizer(cols=2, rows=5, vgap=10, hgap=10)
        fieldsSizer.AddMany([
            (nameLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL),
            (self.nameField,0, wx.EXPAND),
            (orgLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL),
            (self.orgField,0, wx.EXPAND),
            (self.bioLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL),
            (self.bioField, 1, wx.EXPAND),
        ])

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(updateBtn, flag=wx.ALIGN_RIGHT)

        border = wx.BoxSizer(wx.VERTICAL)
        border.Add(topRow, 0, wx.ALL| wx.EXPAND, 5)
        border.Add(fieldsSizer, 1, wx.ALL | wx.EXPAND, 10)
        border.Add(btnSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
        panel.SetSizerAndFit(border)
        self.Fit()
Ejemplo n.º 23
0
    def __init__(self, parent, size=(600, 300), style=wx.NO_BORDER):
        wx.Panel.__init__(self, parent, -1, size=size, style=style)
        self.parent = parent
        self.SetBackgroundColour("white")
        self.session = pavlovia.getCurrentSession()
        # Setup sizer
        self.contentBox = wx.BoxSizer()
        self.SetSizer(self.contentBox)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.contentBox.Add(self.sizer,
                            proportion=1,
                            border=12,
                            flag=wx.ALL | wx.EXPAND)
        # Head sizer
        self.headSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(self.headSizer, border=0, flag=wx.EXPAND)
        # Icon
        self.icon = wx.lib.statbmp.GenStaticBitmap(self,
                                                   ID=wx.ID_ANY,
                                                   bitmap=icons.ButtonIcon(
                                                       stem="user_none",
                                                       size=128).bitmap,
                                                   size=(128, 128))
        self.icon.SetBackgroundColour("#f2f2f2")
        self.headSizer.Add(self.icon, border=6, flag=wx.ALL)
        # Title sizer
        self.titleSizer = wx.BoxSizer(wx.VERTICAL)
        self.headSizer.Add(self.titleSizer, proportion=1, flag=wx.EXPAND)
        # Full name
        self.fullName = wx.StaticText(self,
                                      size=(-1, -1),
                                      label="---",
                                      style=wx.ST_ELLIPSIZE_END)
        self.fullName.SetFont(
            wx.Font(24, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
                    wx.FONTWEIGHT_BOLD))
        self.fullName.Bind(wx.EVT_TEXT, self.updateUser)
        self.titleSizer.Add(self.fullName, border=6, flag=wx.ALL | wx.EXPAND)
        # Organisation
        self.organisation = wx.StaticText(self,
                                          size=(-1, -1),
                                          label="---",
                                          style=wx.ST_ELLIPSIZE_END)
        self.organisation.SetFont(
            wx.Font(12, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_ITALIC,
                    wx.FONTWEIGHT_NORMAL))
        self.titleSizer.Add(self.organisation,
                            border=6,
                            flag=wx.ALL | wx.EXPAND)
        # Spacer
        self.titleSizer.AddStretchSpacer(1)
        # Button sizer
        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.titleSizer.Add(self.btnSizer,
                            border=6,
                            flag=wx.TOP | wx.BOTTOM | wx.EXPAND)
        # Spacer
        self.btnSizer.AddStretchSpacer(1)
        # Pavlovia link
        self.link = wxhl.HyperLinkCtrl(
            self,
            -1,
            label="",
            URL="https://gitlab.pavlovia.org/",
        )
        self.link.SetBackgroundColour(self.GetBackgroundColour())
        self.btnSizer.Add(self.link,
                          border=6,
                          flag=wx.RIGHT | wx.ALIGN_CENTER_VERTICAL)
        # Edit
        self.edit = wx.Button(self, label=chr(int("270E", 16)), size=(24, -1))
        self.edit.Bind(wx.EVT_BUTTON, self.onEdit)
        self.btnSizer.Add(self.edit,
                          border=3,
                          flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL)
        # Switch user
        self.switch = wx.Button(self, label=_translate("Switch User"))
        self.switch.SetBitmap(
            icons.ButtonIcon(stem="view-refresh", size=16).bitmap)
        self.switch.Bind(wx.EVT_BUTTON, self.onSwitchUser)
        self.btnSizer.Add(self.switch,
                          border=3,
                          flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL)
        # Login
        self.login = wx.Button(self, label=_translate("Login"))
        self.login.SetBitmap(
            icons.ButtonIcon(stem="person_off", size=16).bitmap)
        self.login.Bind(wx.EVT_BUTTON, self.onLogin)
        self.btnSizer.Add(self.login, border=3, flag=wx.LEFT | wx.EXPAND)
        # Logout
        self.logout = wx.Button(self, label=_translate("Logout"))
        self.logout.SetBitmap(
            icons.ButtonIcon(stem="person_off", size=16).bitmap)
        self.logout.Bind(wx.EVT_BUTTON, self.onLogout)
        self.btnSizer.Add(self.logout, border=3, flag=wx.LEFT | wx.EXPAND)
        # Sep
        self.sizer.Add(wx.StaticLine(self, -1),
                       border=6,
                       flag=wx.EXPAND | wx.ALL)
        # Bio
        self.description = wx.StaticText(self,
                                         size=(-1, -1),
                                         label="",
                                         style=wx.TE_MULTILINE)
        self.sizer.Add(self.description,
                       proportion=1,
                       border=6,
                       flag=wx.ALL | wx.EXPAND)

        # Populate
        self.user = self.user
Ejemplo n.º 24
0
    def __init__(self,
                 parent=None,
                 id=wx.ID_ANY,
                 style=defStyle,
                 *args,
                 **kwargs):

        wx.Dialog.__init__(self, parent, id, *args, style=style, **kwargs)
        self.SetWindowStyle(wx.STAY_ON_TOP)  # this will be a modal dialog
        panel = wx.Panel(self, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        self.parent = parent
        self.app = wx.GetApp()
        pavSession = pavlovia.getCurrentSession()
        if pavSession.user:
            pavSession.gitlab.auth()
            self.user = pavSession.user
        else:
            self.user = logInPavlovia(parent=parent)
            if not self.user:
                return  # they were given a login but cancelled
        if type(self.user) != pavlovia.User:
            self.user = pavlovia.User(gitlabData=self.user)

        # create the controls
        userField = wxhl.HyperLinkCtrl(panel,
                                       id=wx.ID_ANY,
                                       label=self.user.url,
                                       URL=self.user.url)
        logoutBtn = wx.Button(panel, label="Logout")
        logoutBtn.Bind(wx.EVT_BUTTON, self.onLogout)
        nameLabel = wx.StaticText(panel,
                                  id=wx.ID_ANY,
                                  label=_translate("Full name:"))
        self.nameField = wx.StaticText(panel, wx.ID_ANY, self.user.name)
        bitmapFile = self.user.avatar or "user128invisible.png"
        self.avatarBtn = self.app.iconCache.makeBitmapButton(
            parent=panel,
            filename=bitmapFile,
            label=self.user.name,
            name=self.user.name)

        org = self.user.organization or ""
        orgLabel = wx.StaticText(panel, wx.ID_ANY, _translate("Organization:"))
        self.orgField = wx.StaticText(panel, wx.ID_ANY, org, size=(300, -1))

        bio = self.user.bio or ""
        self.bioLabel = wx.StaticText(panel, wx.ID_ANY,
                                      _translate("Bio (250 chrs):"))
        self.bioField = wx.StaticText(panel,
                                      wx.ID_ANY,
                                      bio,
                                      style=wx.TE_MULTILINE)
        # submit/cancel
        buttonMsg = _translate("OK")
        updateBtn = wx.Button(panel, id=wx.ID_OK, label=buttonMsg)
        updateBtn.Bind(wx.EVT_BUTTON, self.submitChanges)
        # cancelBtn = wx.Button(panel, id=wx.ID_CANCEL, label=_translate("Cancel"))
        # cancelBtn.Bind(wx.EVT_BUTTON, self.onCancel)

        # layout
        userAndLogout = wx.BoxSizer(wx.VERTICAL)
        userAndLogout.Add(userField, 1, wx.ALL | wx.CENTER, 5)
        userAndLogout.Add(logoutBtn, 0, wx.ALL | wx.CENTER, 5)
        topRow = wx.BoxSizer(wx.HORIZONTAL)
        topRow.Add(userAndLogout, 1, wx.ALL | wx.CENTER, 5)
        topRow.Add(self.avatarBtn, 0, wx.ALL | wx.RIGHT, 5)

        fieldsSizer = wx.FlexGridSizer(cols=2, rows=5, vgap=10, hgap=10)
        fieldsSizer.AddMany([
            (nameLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL),
            (self.nameField, 0, wx.EXPAND),
            (orgLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL),
            (self.orgField, 0, wx.EXPAND),
            (self.bioLabel, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL),
            (self.bioField, 1, wx.EXPAND),
        ])

        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.Add(updateBtn)

        border = wx.BoxSizer(wx.VERTICAL)
        border.Add(topRow, 0, wx.ALL | wx.EXPAND, 5)
        border.Add(fieldsSizer, 1, wx.ALL | wx.EXPAND, 10)
        border.Add(btnSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
        panel.SetSizerAndFit(border)
        self.Fit()
Ejemplo n.º 25
0
def syncProject(parent, project, file="", closeFrameWhenDone=False):
    """A function to sync the current project (if there is one)

    Returns
    -----------
        1 for success
        0 for fail
        -1 for cancel at some point in the process
    """
    # Error catch logged out
    session = pavlovia.getCurrentSession()
    if not session or not session.user:
        # If not logged in, prompt to login
        dlg = wx.MessageDialog(None, message=_translate(
            "You are not logged in to Pavlovia. Please log in to sync project."
        ), style=wx.ICON_AUTH_NEEDED | wx.OK | wx.CANCEL)
        dlg.SetOKLabel(_translate("Login..."))
        if dlg.ShowModal() == wx.ID_OK:
            # If they click Login, open login screen
            user = functions.logInPavlovia(None)
            # If they cancelled out of login screen, cancel sync
            if not user:
                return
        else:
            # If they cancel out of login prompt, cancel sync
            return
    # If not in a project, make one
    if project is None:
        msgDlg = wx.MessageDialog(parent,
                               message=_translate("This file doesn't belong to any existing project."),
                               style=wx.OK | wx.CANCEL | wx.CENTER)
        msgDlg.SetOKLabel(_translate("Create a project"))
        if msgDlg.ShowModal() == wx.ID_OK:
            # Get start path and name from builder/coder if possible
            if file:
                file = Path(file)
                name = file.stem
                path = file.parent
            else:
                name = path = ""
            # Open dlg to create new project
            createDlg = sync.CreateDlg(parent,
                                       user=pavlovia.getCurrentSession().user,
                                       name=name,
                                       path=path)
            if createDlg.ShowModal() == wx.ID_OK and createDlg.project is not None:
                project = createDlg.project
            else:
                return
        else:
            return
    # If no local root or dead local root, prompt to make one
    if not project.localRoot or not Path(project.localRoot).is_dir():
        defaultRoot = Path(file).parent
        if not project.localRoot:
            # If there is no local root at all, prompt user to make one
            msg = _translate("Project root folder is not yet specified, specify project root now?")
        elif not Path(project.localRoot).is_dir():
            # If there is a local root but the folder is gone, prompt user to change it
            msg = _translate("Project root folder does not exist, change project root now?")
        # Ask user if they want to
        dlg = wx.MessageDialog(parent, message=msg, style=wx.OK | wx.CANCEL)
        # Get response
        if dlg.ShowModal() == wx.ID_OK:
            # Attempt to get folder of current file
            if file and defaultRoot.is_dir():
                # If we have a reference to the current folder, use it
                project.localRoot = defaultRoot
            else:
                # Otherwise, ask designer to specify manually
                dlg = wx.DirDialog(parent, message=_translate("Specify folder..."), defaultPath=str(defaultRoot))
                if dlg.ShowModal() == wx.ID_OK:
                    project.localRoot = str(dlg.GetPath())
                else:
                    # If cancelled, cancel sync
                    return
        else:
            # If they don't want to specify, cancel sync
            return
    # Assign project to parent frame
    parent.project = project
    # If there is (now) a project, do sync
    if project is not None:
        # Show sync dlg
        dlg = sync.SyncDialog(parent, project)
        # Commit changes
        committed = functions.showCommitDialog(parent, project, initMsg="", infoStream=dlg.status)
        # Cancel sync if commit cancelled
        if committed == -1:
            dlg.status.write(_translate(
                "\n"
                "Sync cancelled by user."
            ))
            dlg.OKbtn.Enable(True)
            return
        # Do sync
        dlg.sync()
Ejemplo n.º 26
0
 def session(self):
     # Cache session if not cached
     if not hasattr(self, "_session"):
         self._session = pavlovia.getCurrentSession()
     # Return cached session
     return self._session
Ejemplo n.º 27
0
    def __init__(self,
                 parent=None,
                 id=wx.ID_ANY,
                 project=None,
                 localRoot="",
                 *args,
                 **kwargs):

        wx.Dialog.__init__(self, parent, id, *args, **kwargs)
        panel = wx.Panel(self, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        # when a project is successfully created these will be populated
        if hasattr(parent, 'filename'):
            self.filename = parent.filename
        else:
            self.filename = None
        self.project = project  # type: PavloviaProject
        self.projInfo = None
        self.parent = parent

        if project:
            # edit existing project
            self.isNew = False
            if project.localRoot and not localRoot:
                localRoot = project.localRoot
        else:
            self.isNew = True

        # create the controls
        nameLabel = wx.StaticText(panel, -1, _translate("Name:"))
        self.nameBox = wx.TextCtrl(panel, -1, size=(400, -1))
        # Path can contain only letters, digits, '_', '-' and '.'.
        # Cannot start with '-', end in '.git' or end in '.atom']
        pavSession = pavlovia.getCurrentSession()

        try:
            username = pavSession.user.username
        except AttributeError as e:
            raise pavlovia.NoUserError(
                "{}: Tried to create project with no user logged in.".format(
                    e))

        gpChoices = [username]
        gpChoices.extend(pavSession.listUserGroups())
        groupLabel = wx.StaticText(panel, -1, _translate("Group/owner:"))
        self.groupBox = wx.Choice(panel, -1, size=(400, -1), choices=gpChoices)

        descrLabel = wx.StaticText(panel, -1, _translate("Description:"))
        self.descrBox = wx.TextCtrl(panel,
                                    -1,
                                    size=(400, 200),
                                    style=wx.TE_MULTILINE | wx.SUNKEN_BORDER)

        localLabel = wx.StaticText(panel, -1, _translate("Local folder:"))
        self.localBox = wx.TextCtrl(panel, -1, size=(400, -1), value=localRoot)
        self.btnLocalBrowse = wx.Button(panel, wx.ID_ANY,
                                        _translate("Browse..."))
        self.btnLocalBrowse.Bind(wx.EVT_BUTTON, self.onBrowseLocal)
        localPathSizer = wx.BoxSizer(wx.HORIZONTAL)
        localPathSizer.Add(self.localBox)
        localPathSizer.Add(self.btnLocalBrowse)

        tagsLabel = wx.StaticText(panel, -1,
                                  _translate("Tags (comma separated):"))
        self.tagsBox = wx.TextCtrl(panel,
                                   -1,
                                   size=(400, 100),
                                   value="PsychoPy, Builder, Coder",
                                   style=wx.TE_MULTILINE | wx.SUNKEN_BORDER)
        publicLabel = wx.StaticText(panel, -1, _translate("Public:"))
        self.publicBox = wx.CheckBox(panel, -1)

        # buttons
        if self.isNew:
            buttonMsg = _translate("Create project on Pavlovia")
        else:
            buttonMsg = _translate("Submit changes to Pavlovia")
        updateBtn = wx.Button(panel, -1, buttonMsg)
        updateBtn.Bind(wx.EVT_BUTTON, self.submitChanges)
        cancelBtn = wx.Button(panel, -1, _translate("Cancel"))
        cancelBtn.Bind(wx.EVT_BUTTON, self.onCancel)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.AddMany([updateBtn, cancelBtn])

        # do layout
        fieldsSizer = wx.FlexGridSizer(cols=2, rows=6, vgap=5, hgap=5)
        fieldsSizer.AddMany([(nameLabel, 0, wx.ALIGN_RIGHT), self.nameBox,
                             (groupLabel, 0, wx.ALIGN_RIGHT), self.groupBox,
                             (localLabel, 0, wx.ALIGN_RIGHT), localPathSizer,
                             (descrLabel, 0, wx.ALIGN_RIGHT), self.descrBox,
                             (tagsLabel, 0, wx.ALIGN_RIGHT), self.tagsBox,
                             (publicLabel, 0, wx.ALIGN_RIGHT), self.publicBox])

        border = wx.BoxSizer(wx.VERTICAL)
        border.Add(fieldsSizer, 0, wx.ALL, 5)
        border.Add(btnSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
        panel.SetSizerAndFit(border)
        self.Fit()
Ejemplo n.º 28
0
def syncProject(parent, project, file="", closeFrameWhenDone=False):
    """A function to sync the current project (if there is one)

    Returns
    -----------
        1 for success
        0 for fail
        -1 for cancel at some point in the process
    """
    # If not in a project, make one
    if project is None:
        msgDlg = wx.MessageDialog(
            parent,
            message=_translate(
                "This file doesn't belong to any existing project."),
            style=wx.OK | wx.CANCEL | wx.CENTER)
        msgDlg.SetOKLabel(_translate("Create a project"))
        if msgDlg.ShowModal() == wx.ID_OK:
            # Get start path and name from builder/coder if possible
            if file:
                file = Path(file)
                name = file.stem
                path = file.parent
            else:
                name = path = ""
            # Open dlg to create new project
            createDlg = sync.CreateDlg(parent,
                                       user=pavlovia.getCurrentSession().user,
                                       name=name,
                                       path=path)
            if createDlg.ShowModal(
            ) == wx.ID_OK and createDlg.project is not None:
                project = createDlg.project
            else:
                return
        else:
            return
    # If no local root, prompt to make one
    if not project.localRoot:
        defaultRoot = Path(file).parent
        # Ask user if they want to
        dlg = wx.MessageDialog(
            parent,
            message=_translate(
                "Project root folder is not yet specified, specify one now?"),
            style=wx.YES_NO)
        # Open folder picker
        if dlg.ShowModal() == wx.ID_YES:
            dlg = wx.DirDialog(parent,
                               message=_translate("Specify folder..."),
                               defaultPath=str(defaultRoot))
            if dlg.ShowModal() == wx.ID_OK:
                localRoot = Path(dlg.GetPath())
                project.localRoot = str(localRoot)
            else:
                # If cancelled, cancel sync
                return
        else:
            # If they don't want to specify, cancel sync
            return
    # Assign project to parent frame
    parent.project = project
    # If there is (now) a project, do sync
    if project is not None:
        dlg = sync.SyncDialog(parent, project)
        functions.showCommitDialog(parent,
                                   project,
                                   initMsg="",
                                   infoStream=dlg.status)
        dlg.sync()
Ejemplo n.º 29
0
def syncProject(parent, project=None, closeFrameWhenDone=False):
    """A function to sync the current project (if there is one)

    Returns
    -----------
        1 for success
        0 for fail
        -1 for cancel at some point in the process
    """
    if not pavlovia.haveGit:
        noGitWarning(parent)
        return 0

    isCoder = hasattr(parent, 'currentDoc')
    if not project and "BuilderFrame" in repr(parent):
        # try getting one from the frame
        project = parent.project  # type: pavlovia.PavloviaProject

    if not project:  # ask the user to create one

        # if we're going to create a project we need user to be logged in
        pavSession = pavlovia.getCurrentSession()
        try:
            username = pavSession.user.username
        except:
            username = logInPavlovia(parent)
        if not username:
            return -1  # never logged in

        # create project dialog
        msg = _translate("This file doesn't belong to any existing project.")
        style = wx.OK | wx.CANCEL | wx.CENTER
        dlg = wx.MessageDialog(parent=parent, message=msg, style=style)
        dlg.SetOKLabel(_translate("Create a project"))
        if dlg.ShowModal() == wx.ID_OK:
            if isCoder:
                if parent.currentDoc:
                    localRoot = os.path.dirname(parent.currentDoc.filename)
                else:
                    localRoot = ''
            else:
                localRoot = os.path.dirname(parent.filename)
            # open the project editor (with no project to create one)
            editor = ProjectEditor(parent=parent, localRoot=localRoot)
            if editor.ShowModal() == wx.ID_OK:
                project = editor.project
            else:
                project = None
        else:
            return -1  # user pressed cancel

    if not project:  # we did our best for them. Give up!
        return 0

    # if project.localRoot doesn't exist, or is empty
    if 'localRoot' not in project or not project.localRoot:
        # we first need to choose a location for the repository
        setLocalPath(parent, project)
        parent.Raise()  # make sure that frame is still visible

    #check that the project does exist remotely
    if not project.pavlovia:
        # project didn't exist at Pavlovia (deleted?)
        recreatorDlg = ProjectRecreator(parent=parent, project=project)
        ok = recreatorDlg.ShowModal()
        if ok > 0:
            project = recreatorDlg.project
        else:
            logging.error("Failed to recreate project to sync with")
            return 0

    # a sync will be necessary so can create syncFrame
    syncFrame = sync.SyncFrame(parent=parent, id=wx.ID_ANY, project=project)

    if project._newRemote:
        # new remote so this will be a first push
        if project.getRepo(forceRefresh=True) is None:
            # no local repo yet so create one
            project.newRepo(syncFrame)
        # add the local files and commit them
        ok = showCommitDialog(parent=parent,
                              project=project,
                              initMsg="First commit",
                              infoStream=syncFrame.syncPanel.infoStream)
        if ok == -1:  # cancelled
            syncFrame.Destroy()
            return -1
        syncFrame.syncPanel.setStatus("Pushing files to Pavlovia")
        wx.Yield()
        time.sleep(0.001)
        # git push -u origin master
        try:
            project.firstPush(infoStream=syncFrame.syncPanel.infoStream)
            project._newRemote = False
        except Exception as e:
            closeFrameWhenDone = False
            syncFrame.syncPanel.statusAppend(traceback.format_exc())
    else:
        # existing remote which we should sync (or clone)
        try:
            ok = project.getRepo(syncFrame.syncPanel.infoStream)
            if not ok:
                closeFrameWhenDone = False
        except Exception as e:
            closeFrameWhenDone = False
            syncFrame.syncPanel.statusAppend(traceback.format_exc())
        # check for anything to commit before pull/push
        outcome = showCommitDialog(parent,
                                   project,
                                   infoStream=syncFrame.syncPanel.infoStream)
        # 0=nothing to do, 1=OK, -1=cancelled
        if outcome == -1:  # user cancelled
            syncFrame.Destroy()
            return -1
        try:
            status = project.sync(syncFrame.syncPanel.infoStream)
            if status == -1:
                syncFrame.syncPanel.statusAppend("Couldn't sync")
        except Exception:  # not yet sure what errors might occur
            # send the error to panel
            syncFrame.syncPanel.statusAppend(traceback.format_exc())
            return 0

    wx.Yield()
    project._lastKnownSync = time.time()
    if closeFrameWhenDone:
        syncFrame.Destroy()

    return 1
Ejemplo n.º 30
0
    def __init__(self, parent, viewer, size=(400, -1), style=wx.NO_BORDER):
        # Init self
        wx.Panel.__init__(self, parent, -1, size=size, style=style)
        self.session = pavlovia.getCurrentSession()
        # Setup sizer
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        # Add search ctrl
        self.searchCtrl = wx.SearchCtrl(self)
        self.searchCtrl.Bind(wx.EVT_SEARCH, self.search)
        self.sizer.Add(self.searchCtrl, border=4, flag=wx.EXPAND | wx.ALL)
        # Add button sizer
        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(self.btnSizer, border=4, flag=wx.EXPAND | wx.ALL)
        # Add "me mode" button
        self.mineBtn = wx.ToggleButton(self,
                                       size=(64, -1),
                                       label=_translate("Me"))
        self.mineBtn.SetBitmap(
            icons.ButtonIcon(stem="person_off", size=16).bitmap)
        self.mineBtn.SetBitmapFocus(
            icons.ButtonIcon(stem="person_on", size=16).bitmap)
        self.mineBtn.SetBitmapPressed(
            icons.ButtonIcon(stem="person_on", size=16).bitmap)
        self._mine = False
        self.mineBtn.Bind(wx.EVT_TOGGLEBUTTON, self.onMineBtn)
        self.mineBtn.Enable(self.session.userID is not None)
        self.btnSizer.Add(self.mineBtn,
                          border=6,
                          flag=wx.EXPAND | wx.RIGHT | wx.TOP | wx.BOTTOM)
        self.btnSizer.AddStretchSpacer(1)
        # Add sort button
        self.sortBtn = wx.Button(self, label=_translate("Sort..."))
        self.sortOrder = []
        self.sortBtn.Bind(wx.EVT_BUTTON, self.sort)
        self.btnSizer.Add(self.sortBtn,
                          border=6,
                          flag=wx.LEFT | wx.RIGHT | wx.TOP | wx.BOTTOM)
        # Add filter button
        self.filterBtn = wx.Button(self, label=_translate("Filter..."))
        self.filterTerms = {
            "Status": [],
            "Platform": [],
            "Keywords": [],
        }
        self.filterOptions = {
            "Author": None,
            "Status": ["running", "piloting", "inactive"],
            "Platform":
            ["psychojs", "jspsych", "labjs", "opensesame", "other"],
            "Visibility": ["public", "private"],
            "Keywords": None,
        }
        self.filterBtn.Bind(wx.EVT_BUTTON, self.filter)
        self.btnSizer.Add(self.filterBtn,
                          border=6,
                          flag=wx.LEFT | wx.TOP | wx.BOTTOM)
        # Add filter label
        self.filterLbl = self.FilterLabel(self, style=wx.ST_ELLIPSIZE_END)
        self.filterLbl.Bind(wx.EVT_ENTER_WINDOW, self.filterLbl.hoverOn)
        self.filterLbl.Bind(wx.EVT_LEAVE_WINDOW, self.filterLbl.hoverOff)
        self.sizer.Add(self.filterLbl, border=6, flag=wx.LEFT | wx.RIGHT)
        self.filterLbl.update()
        # Add project list
        self.projectList = ListCtrl(self,
                                    size=(-1, -1),
                                    style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
        self.projectList.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.showProject)
        self.sizer.Add(self.projectList,
                       proportion=1,
                       border=4,
                       flag=wx.EXPAND | wx.ALL)
        # Setup project list
        self.projectList.InsertColumn(0,
                                      _starred,
                                      width=36,
                                      format=wx.LIST_FORMAT_CENTER)  # Stars
        #self.projectList.InsertColumn(1, _translate('Status'), width=wx.LIST_AUTOSIZE, format=wx.LIST_FORMAT_LEFT)  # Status
        self.projectList.InsertColumn(2,
                                      _translate('Author'),
                                      width=wx.LIST_AUTOSIZE,
                                      format=wx.LIST_FORMAT_LEFT)  # Author
        self.projectList.InsertColumn(3,
                                      _translate('Name'),
                                      width=wx.LIST_AUTOSIZE,
                                      format=wx.LIST_FORMAT_LEFT)  # Name
        # Setup projects dict
        self.projects = None

        # Link ProjectViewer
        self.viewer = viewer
        self.projectList.Bind(wx.EVT_LIST_ITEM_SELECTED, self.showProject)
        # Layout
        self.Layout()

        # Initial search
        self.search()
Ejemplo n.º 31
0
    def __init__(self, parent=None, id=wx.ID_ANY, project=None, localRoot="",
                 *args, **kwargs):

        wx.Dialog.__init__(self, parent, id,
                           *args, **kwargs)
        panel = wx.Panel(self, wx.ID_ANY, style=wx.TAB_TRAVERSAL)
        # when a project is successfully created these will be populated
        if hasattr(parent, 'filename'):
            self.filename = parent.filename
        else:
            self.filename = None
        self.project = project  # type: PavloviaProject
        self.projInfo = None
        self.parent = parent

        if project:
            # edit existing project
            self.isNew = False
            if project.localRoot and not localRoot:
                localRoot = project.localRoot
        else:
            self.isNew = True

        # create the controls
        nameLabel = wx.StaticText(panel, -1, _translate("Name:"))
        self.nameBox = wx.TextCtrl(panel, -1, size=(400, -1))
        # Path can contain only letters, digits, '_', '-' and '.'.
        # Cannot start with '-', end in '.git' or end in '.atom']
        pavSession = pavlovia.getCurrentSession()

        try:
            username = pavSession.user.username
        except AttributeError as e:
            raise pavlovia.NoUserError("{}: Tried to create project with no user logged in.".format(e))

        gpChoices = [username]
        gpChoices.extend(pavSession.listUserGroups())
        groupLabel = wx.StaticText(panel, -1, _translate("Group/owner:"))
        self.groupBox = wx.Choice(panel, -1, size=(400, -1),
                                  choices=gpChoices)

        descrLabel = wx.StaticText(panel, -1, _translate("Description:"))
        self.descrBox = wx.TextCtrl(panel, -1, size=(400, 200),
                                    style=wx.TE_MULTILINE | wx.SUNKEN_BORDER)

        localLabel = wx.StaticText(panel, -1, _translate("Local folder:"))
        self.localBox = wx.TextCtrl(panel, -1, size=(400, -1),
                                    value=localRoot)
        self.btnLocalBrowse = wx.Button(panel, wx.ID_ANY, _translate("Browse..."))
        self.btnLocalBrowse.Bind(wx.EVT_BUTTON, self.onBrowseLocal)
        localPathSizer = wx.BoxSizer(wx.HORIZONTAL)
        localPathSizer.Add(self.localBox)
        localPathSizer.Add(self.btnLocalBrowse)

        tagsLabel = wx.StaticText(panel, -1,
                                  _translate("Tags (comma separated):"))
        self.tagsBox = wx.TextCtrl(panel, -1, size=(400, 100),
                                   value="PsychoPy, Builder, Coder",
                                   style=wx.TE_MULTILINE | wx.SUNKEN_BORDER)
        publicLabel = wx.StaticText(panel, -1, _translate("Public:"))
        self.publicBox = wx.CheckBox(panel, -1)

        # buttons
        if self.isNew:
            buttonMsg = _translate("Create project on Pavlovia")
        else:
            buttonMsg = _translate("Submit changes to Pavlovia")
        updateBtn = wx.Button(panel, -1, buttonMsg)
        updateBtn.Bind(wx.EVT_BUTTON, self.submitChanges)
        cancelBtn = wx.Button(panel, -1, _translate("Cancel"))
        cancelBtn.Bind(wx.EVT_BUTTON, self.onCancel)
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.AddMany([updateBtn, cancelBtn])

        # do layout
        fieldsSizer = wx.FlexGridSizer(cols=2, rows=6, vgap=5, hgap=5)
        fieldsSizer.AddMany([(nameLabel, 0, wx.ALIGN_RIGHT), self.nameBox,
                             (groupLabel, 0, wx.ALIGN_RIGHT), self.groupBox,
                             (localLabel, 0, wx.ALIGN_RIGHT), localPathSizer,
                             (descrLabel, 0, wx.ALIGN_RIGHT), self.descrBox,
                             (tagsLabel, 0, wx.ALIGN_RIGHT), self.tagsBox,
                             (publicLabel, 0, wx.ALIGN_RIGHT), self.publicBox])

        border = wx.BoxSizer(wx.VERTICAL)
        border.Add(fieldsSizer, 0, wx.ALL, 5)
        border.Add(btnSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
        panel.SetSizerAndFit(border)
        self.Fit()
Ejemplo n.º 32
0
def syncProject(parent, project=None, closeFrameWhenDone=False):
    """A function to sync the current project (if there is one)

    Returns
    -----------
        1 for success
        0 for fail
        -1 for cancel at some point in the process
    """
    if not pavlovia.haveGit:
        noGitWarning(parent)
        return 0

    isCoder = hasattr(parent, 'currentDoc')
    if not project and "BuilderFrame" in repr(parent):
        # try getting one from the frame
        project = parent.project  # type: pavlovia.PavloviaProject

    if not project:  # ask the user to create one

        # if we're going to create a project we need user to be logged in
        pavSession = pavlovia.getCurrentSession()
        try:
            username = pavSession.user.username
        except:
            username = logInPavlovia(parent)
        if not username:
            return -1  # never logged in

        # create project dialog
        msg = _translate("This file doesn't belong to any existing project.")
        style = wx.OK | wx.CANCEL | wx.CENTER
        dlg = wx.MessageDialog(parent=parent, message=msg, style=style)
        dlg.SetOKLabel(_translate("Create a project"))
        if dlg.ShowModal() == wx.ID_OK:
            if isCoder:
                if parent.currentDoc:
                    localRoot = os.path.dirname(parent.currentDoc.filename)
                else:
                    localRoot = ''
            else:
                localRoot = os.path.dirname(parent.filename)
            # open the project editor (with no project to create one)
            editor = ProjectEditor(parent=parent, localRoot=localRoot)
            if editor.ShowModal() == wx.ID_OK:
                project = editor.project
            else:
                project = None
        else:
            return -1  # user pressed cancel

    if not project:  # we did our best for them. Give up!
        return 0

    # if project.localRoot doesn't exist, or is empty
    if 'localRoot' not in project or not project.localRoot:
        # we first need to choose a location for the repository
        setLocalPath(parent, project)
        parent.Raise()  # make sure that frame is still visible

    #check that the project does exist remotely
    if not project.pavlovia:
        # project didn't exist at Pavlovia (deleted?)
        recreatorDlg = ProjectRecreator(parent=parent, project=project)
        ok = recreatorDlg.ShowModal()
        if ok > 0:
            project = recreatorDlg.project
        else:
            logging.error("Failed to recreate project to sync with")
            return

    # a sync will be necessary so can create syncFrame
    syncFrame = sync.SyncFrame(parent=parent, id=wx.ID_ANY, project=project)

    if project._newRemote:
        # new remote so this will be a first push
        if project.getRepo(forceRefresh=True) is None:
            # no local repo yet so create one
            project.newRepo(syncFrame)
        # add the local files and commit them
        ok = showCommitDialog(parent=parent, project=project,
                              initMsg="First commit",
                              infoStream=syncFrame.syncPanel.infoStream)
        if ok == -1:  # cancelled
            syncFrame.Destroy()
            return -1
        syncFrame.syncPanel.setStatus("Pushing files to Pavlovia")
        wx.Yield()
        time.sleep(0.001)
        # git push -u origin master
        try:
            project.firstPush(infoStream=syncFrame.syncPanel.infoStream)
            project._newRemote = False
        except Exception as e:
            closeFrameWhenDone = False
            syncFrame.syncPanel.statusAppend(traceback.format_exc())
    else:
        # existing remote which we should sync (or clone)
        try:
            ok = project.getRepo(syncFrame.syncPanel.infoStream)
            if not ok:
                closeFrameWhenDone = False
        except Exception as e:
            closeFrameWhenDone = False
            syncFrame.syncPanel.statusAppend(traceback.format_exc())
        # check for anything to commit before pull/push
        outcome = showCommitDialog(parent, project,
                                   infoStream=syncFrame.syncPanel.infoStream)
        # 0=nothing to do, 1=OK, -1=cancelled
        if outcome == -1:  # user cancelled
            syncFrame.Destroy()
            return -1
        try:
            status = project.sync(syncFrame.syncPanel.infoStream)
            if status == -1:
                syncFrame.syncPanel.statusAppend("Couldn't sync")
        except Exception:  # not yet sure what errors might occur
            # send the
            closeFrameWhenDone = False
            syncFrame.syncPanel.statusAppend(traceback.format_exc())

    wx.Yield()
    project._lastKnownSync = time.time()
    if closeFrameWhenDone:
        syncFrame.Destroy()

    return 1