Unit testing Spreadsheet WB copy and paste

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
chennes
Veteran
Posts: 3911
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Unit testing Spreadsheet WB copy and paste

Post by chennes »

I'm trying to write some unit tests for Spreadsheet's copy and paste functions, and I'm struggling to get it to work. I've written the C++-to-Python wrapper that gets me access to the QTableView widget, so that I can then write:

Code: Select all

   def testCopySingleCell(self):
        self.injectSimpleData()
        self.sheet.ViewObject.doubleClicked()
        model = self.view.model()
        self.view.selectionModel().select(model.createIndex(0, 0), QtCore.QItemSelectionModel.ClearAndSelect)
        FreeCAD.Gui.runCommand("Std_Copy", 0)
        self.view.selectionModel().select(model.createIndex(4, 4), QtCore.QItemSelectionModel.ClearAndSelect)
        FreeCAD.Gui.runCommand("Std_Paste", 0)
        self.doc.recompute()
        self.assertEqual(self.sheet.get("A1"), self.sheet.get("E5"))
Unfortunately, when running the copy and paste commands like this, nothing happens, so the assertion fails. Can anyone help clarify a) why this doesn't work, and b) what the correct approach is?
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
wmayer
Founder
Posts: 20310
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by wmayer »

The copy&paste commands send messages ("Copy" or "Paste" respectively) to the active view. Maybe the spreadsheet is not the active window?
User avatar
chennes
Veteran
Posts: 3911
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by chennes »

That's almost certainly the cause: if I run the test from the command line, it passes without any problems, it's only when I run from the Test Workbench GUI that it fails. So presumably the events are going to the Test Workbench runner window and not to the Spreadsheet in the MDI. Do you have any suggestion for how to overcome this? I'd like the tests to work from the GUI as well as the command line.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
wmayer
Founder
Posts: 20310
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by wmayer »

I think I have found the problem. Inside StdCmdCopy::activated/StdCmdPaste::activated the function sendMsgToFocusView() is called and when looking at its implementation shows why it fails in your case:

Code: Select all

bool Application::sendMsgToFocusView(const char* pMsg, const char** ppReturn)
{
    MDIView* pView = getMainWindow()->activeWindow();
    if(!pView)
        return false;
    for(auto focus=qApp->focusWidget();focus;focus=focus->parentWidget()) {
        if(focus == pView) {
            bool res = pView->onMsg(pMsg,ppReturn);
            updateActions(true);
            return res;
        }
    }
    return false;
}
If you start the unit test then the dialog has the focus and because it's not a child of the MDI view the message will never be sent.

In the past we called the function sendMsgToActiveView() and realthunder has changed it with git commit bd2f5191c9d3d3adfaf6. The commit message says:
send(Has)MsgToFocusView(), new API to send message to the active view
in focus. This is to solve the ambiguity of things like pressing
delete key, copy, paste handling when the active new is not in focus.
For example, when spread sheet view is active, delete/copy/paste
handling should be different when the focus on the spread sheet view
or focus on tree view.
So, to solve your problem you have several options:
  • Try to make sure that the spreadsheet view has the focus
  • Use the deprecated method Gui.SendMsgToActiveView
  • The preferred way is to access the spreadsheet view and directly call the method to send the message. Unfortunately, this method is not yet visible in the Python wrapper. I will have a look at this...
wmayer
Founder
Posts: 20310
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by wmayer »

I made several changes to the spreadsheet module and now you can write:

Code: Select all

vp = ... # access the view provider
view = vp.getView() # might be None
view.sendMessage("Copy")
vp.setCurrentIndex("A4")
view.sendMessage("Paste")
User avatar
chennes
Veteran
Posts: 3911
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by chennes »

That's fantastic, thank you! I learned a lot about our Python integration today :) . I'm inclined to move most of those Python functions from the View Provider into the SheetView, now that you've given us access to it. That way they match where they are in the C++.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
DanielLeeWenger
Posts: 53
Joined: Sun Feb 02, 2020 4:02 am
Location: Santa Cruz, California
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by DanielLeeWenger »

This looks very interesting. I want to be able to view an active document and send "Run" to the Macro editor via a Macro button.

I suspect that this would be possible when the new code migrates to a distributed version of FC? Perhaps there is a way of doing what I want already?
TheMarkster
Veteran
Posts: 5513
Joined: Thu Apr 05, 2018 1:53 am

Re: Unit testing Spreadsheet WB copy and paste

Post by TheMarkster »

When loading into the editor the macro gets placed at the top of the recent macros list. So, by default, Ctrl+Shift+1 would run the macro.
wmayer
Founder
Posts: 20310
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by wmayer »

With the current version git commit 751227402d it's possible to access an MDI view by its type name.

Code: Select all

mw = Gui.getMainWindow()
py = mw.getWindowsOfType(App.Base.TypeId.fromName("Gui::PythonEditorView"))[0]
py.sendMessage("Run")
Hint: With git commit 6bf724cca9ef61 some extra functions have been added to the PySide wrapper of Gui::MainWindow. But these extra methods do not appear in the call tips list of the Python console.
DanielLeeWenger
Posts: 53
Joined: Sun Feb 02, 2020 4:02 am
Location: Santa Cruz, California
Contact:

Re: Unit testing Spreadsheet WB copy and paste

Post by DanielLeeWenger »

Wow. This forum is fantastic. Thank you Markster and wmayer. I have a choice as how to do what I want.
Post Reply