Macro Snip: Difference between revisions

From FreeCAD Documentation
No edit summary
Line 94: Line 94:
__Wiki__ = ""
__Wiki__ = ""
__date__ = "2019.08.04"
__date__ = "2019.08.04"
__version__ = 1.03
__version__ = 1.04




import FreeCAD
import FreeCAD
from PySide import QtGui,QtCore
from PySide import QtGui,QtCore
from PySide2 import QtWidgets
import uuid
import uuid
import time
import time
import tempfile, os, shutil


#credit serge_gubenko of stackoverflow for this resizable QMessageBox
#credit serge_gubenko of stackoverflow for this resizable QMessageBox
Line 136: Line 136:
image = clip.image(QtGui.QClipboard.Clipboard)
image = clip.image(QtGui.QClipboard.Clipboard)
if not image:
if not image:
if hasattr(QtGui.QApplication,"primaryScreen"):
#use our own screen grabber
#use our own screen grabber
mb = MyMessageBox()
mb = MyMessageBox()
mb.setStandardButtons(QtGui.QMessageBox.Ok.__or__(QtGui.QMessageBox.Cancel))
mb.setStandardButtons(QtGui.QMessageBox.Ok.__or__(QtGui.QMessageBox.Cancel))
details = """
details = """
Move and resize this box to cover the part of the screen you wish to grab.
Move and resize this box to cover the part of the screen you wish to grab.
If it succeeds an open file dialog will appear. Drag and drop the file
If it succeeds an open file dialog will appear. Drag and drop the file
Line 167: Line 168:


"""
"""
mb.setWindowTitle("Snip macro")
mb.setWindowTitle("Snip macro v"+str(__version__))
mb.setDetailedText(details)
mb.setDetailedText(details)
mb.setWindowOpacity(0.85)
mb.setWindowOpacity(0.85)
pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Snip_Macro")
pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Snip_Macro")
lastX = pg.GetInt("LastX",0)
lastX = pg.GetInt("LastX",0)
lastY = pg.GetInt("LastY",0)
lastY = pg.GetInt("LastY",0)
lastWidth = pg.GetInt("LastWidth",100)
lastWidth = pg.GetInt("LastWidth",100)
lastHeight = pg.GetInt("LastHeight",100)
lastHeight = pg.GetInt("LastHeight",100)
mb.setGeometry(lastX, lastY, lastWidth, lastHeight)
mb.setGeometry(lastX, lastY, lastWidth, lastHeight)
mb.setWindowFlags(QtCore.Qt.Tool)
mb.setWindowFlags(QtCore.Qt.Tool)
result = mb.exec_()
result = mb.exec_()
if result != QtGui.QMessageBox.Ok:
if result != QtGui.QMessageBox.Ok:
userCanceled = True
if not userCanceled:
rect = mb.frameGeometry()
pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Snip_Macro")
pg.SetInt("LastX", rect.x())
pg.SetInt("LastY", rect.y())
pg.SetInt("LastWidth", rect.width())
pg.SetInt("LastHeight", rect.height())
QtGui.QApplication.processEvents()
time.sleep(.5) #give time for dialog to close before taking screenshot
QtGui.QApplication.processEvents()
screen = QtGui.QApplication.primaryScreen()
image = screen.grabWindow(0,rect.x(),rect.y(),rect.width(),rect.height()).toImage()
if not image:
raise Exception("Snip Macro Error: Unable to grab screen image\n")
else:
QtGui.QMessageBox.critical(QtGui.QMainWindow(),"Unsupported","Your version of Qt is not supported for taking screenshots.\n\
It is recommended to update to a newer version of FreeCAD with Qt5+, but you can still use the macro \
for images already copied to the clipboard.\n\n\
Windows snip tool: Window Key + Shift + S\n\
Mac snip tool: Command + Shift + 4\n\
Linux: gnome-screenshot utility\n")
userCanceled = True
userCanceled = True
if not userCanceled:
if not userCanceled:
rect = mb.frameGeometry()
dirPath = tempfile.mkdtemp()
filePath = dirPath + os.path.sep + fname
pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Snip_Macro")
image.save(filePath)
pg.SetInt("LastX", rect.x())
fileName = QtGui.QFileDialog.getOpenFileName(QtGui.QApplication.activeWindow(),
pg.SetInt("LastY", rect.y())
"Drag the image to the forum, then Cancel will delete the temporary file", dirPath, "PNG (*.png)")
pg.SetInt("LastWidth", rect.width())
if fileName[0]: #user selected Open or double-clicked file
pg.SetInt("LastHeight", rect.height())
import subprocess, os, platform
if platform.system() == 'Darwin': # macOS
subprocess.call(('open', fileName[0]))
elif platform.system() == 'Windows': # Windows
os.startfile(fileName[0])
else: # linux variants
subprocess.call(('xdg-open', fileName[0]))
QtGui.QApplication.processEvents() #allow some time for file to open before deleting temp folder and contents
time.sleep(1)
QtGui.QApplication.processEvents()
QtGui.QApplication.processEvents()
shutil.rmtree(dirPath)
time.sleep(.5) #give time for dialog to close before taking screenshot
QtGui.QApplication.processEvents()
screen = QtGui.QApplication.primaryScreen()
image = screen.grabWindow(0,rect.x(),rect.y(),rect.width(),rect.height()).toImage()
if not image:
raise Exception("Snip Macro Error: Unable to grab screen image\n")
if not userCanceled:
dir = QtCore.QTemporaryDir()
filePath = dir.filePath(fname)
if dir.isValid():
image.save(filePath)
fileName = QtGui.QFileDialog.getOpenFileName(QtGui.QApplication.activeWindow(),
"Drag the image to the forum, then Cancel will delete the temporary file", dir.path(), "PNG (*.png)")
if fileName[0]: #user selected Open or double-clicked file
import subprocess, os, platform
if platform.system() == 'Darwin': # macOS
subprocess.call(('open', fileName[0]))
elif platform.system() == 'Windows': # Windows
os.startfile(fileName[0])
else: # linux variants
subprocess.call(('xdg-open', fileName[0]))
else:
dir.remove()
else:
raise Exception("Snip Macro Error: Unable to create temporary directory.\n")
}}
}}

Revision as of 21:52, 4 August 2019

Snip

Description
Use this macro to easily post screenshots to the FreeCAD forum.

Macro version: 1.03
Last modified: 2019-08-04
FreeCAD version: All
Download: ToolBar Icon
Author: TheMarkster
Author
TheMarkster
Download
ToolBar Icon
Links
Macro Version
1.03
Date last modified
2019-08-04
FreeCAD Version(s)
All
Default shortcut
None
See also
None


Description

Use this macro to easily post screenshots to the FreeCAD forum.

It is best to add this macro to your global custom macros toolbar for quick and easy access.

When posting to the FreeCAD forum it is often useful to be able to include screenshots. The problem is this is a somewhat tedious task. This macro is to make that task a bit easier.

The macro can take screenshots or it can use existing screenshots that have already been copied to the system clipboard. To bypass the image already in clipboard press the Shift key while invoking the macro. To use the macro to take the screenshot adjust the size and placement of the dialog that pops up, then click OK. Upon clicking OK the macro will attempt to take a screenshot of the area of the screen covered by the dialog. The dialog itself is semi-transparent, so you can see the contents beneath.

Snip screenshot1, Notice how the dialog is semi-transparent. Only the screen contents below the dialog will be captured.

After clicking OK, the macro then takes the screenshot and saves it to a temporary file. A file open dialog is then opened at the file's location. You can drag and drop the file from there to the forum into the textarea where you type in your text for your forum post. Upon canceling the dialog the temporary screenshot file is deleted automatically. You may also open the screenshot file in your default application installed for opening .png files. On Windows this is typically Paint. This can be useful if you wish to add some annotations to the screenshot or perhaps additional editing, such as cropping.

Snip screenshot2, This is the open file dialog that pops up automatically after taking the screenshot. The image can be dragged and dropped to the forum or it can be opened for further processing in your system default application for opening png files. Alternatively, you can right-click on the image and open with.. another application of your choice.

If the macro doesn't work on your system to capture screenshots it can still be useful for screenshots you have captured using other tools. Simply copy the screenshot to the clipboard, then run the macro. It will create the temporary file and open the file's directory in an open file dialog for you. Some other tools for taking screenshots:

On Windows: Windows Key + Shift + S
On Mac: Command + Shift + 4
On Linux: gnone-screenshot utility

Script

ToolBar icon

Macro_Snip.FCMacro

# -*- coding: utf-8 -*-
"""
***************************************************************************
*   Copyright (c) 2019 <TheMarkster>                                 *
*                                                                         *
*   This file is a supplement to the FreeCAD CAx development system.      *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU Lesser General Public License (LGPL)    *
*   as published by the Free Software Foundation; either version 2 of     *
*   the License, or (at your option) any later version.                   *
*                                                                         *
*   This software is distributed in the hope that it will be useful,      *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU Library General Public License at http://www.gnu.org/licenses     *
*   for more details.                                                     *
*                                                                         *
*   For more information about the GNU Library General Public License     *
*   write to the Free Software Foundation, Inc., 59 Temple Place,         *
*   Suite 330, Boston, MA  02111-1307 USA                                 *
*                                                                         *
***************************************************************************
"""



"""
Snip Macro

This is a macro to make it easier to post screenshots to the FreeCAD forum.

The forum supports a drag and drop interface -- just drag and drop an image to the
textarea where you type in your post.  But it still requires many
tedious steps.  This macro is to reduce some of those steps.

You should add the macro to your custom macro toolbar to save as many clicks as possible.

The first thing the macro does is to check if there is an image already saved to the 
system clipboard, and if so, it uses that one.  To bypass the clipboard, press Shift
while invoking the macro.

"""

__title__ = "Snip"
__author__ = "TheMarkster"
__url__ = ""
__Wiki__ = ""
__date__ = "2019.08.04"
__version__ = 1.04


import FreeCAD
from PySide import QtGui,QtCore
import uuid
import time
import tempfile, os, shutil

#credit serge_gubenko of stackoverflow for this resizable QMessageBox
class MyMessageBox(QtGui.QMessageBox):
    def __init__(self):
        QtGui.QMessageBox.__init__(self)
        #self.setSizeGripEnabled(True)
    def event(self, e):
        result = QtGui.QMessageBox.event(self, e)
        self.setMinimumHeight(0)
        self.setMaximumHeight(16777215)
        self.setMinimumWidth(0)
        self.setMaximumWidth(16777215)
        self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        textEdit = self.findChild(QtGui.QTextEdit)
        if textEdit != None :
            textEdit.setMinimumHeight(0)
            textEdit.setMaximumHeight(16777215)
            textEdit.setMinimumWidth(0)
            textEdit.setMaximumWidth(16777215)
            textEdit.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        return result

skipClipboard = False
modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers == QtCore.Qt.ShiftModifier:
    skipClipboard = True

userCanceled = False
fname = "Snip macro screenshot-"+str(uuid.uuid4())[:6]+".png"
image = None
if not skipClipboard:
    clip = QtGui.QClipboard()
    image = clip.image(QtGui.QClipboard.Clipboard)
if not image:
    if hasattr(QtGui.QApplication,"primaryScreen"):
        #use our own screen grabber
        mb = MyMessageBox()
        mb.setStandardButtons(QtGui.QMessageBox.Ok.__or__(QtGui.QMessageBox.Cancel))
        details = """
Move and resize this box to cover the part of the screen you wish to grab.
If it succeeds an open file dialog will appear.  Drag and drop the file
from the open file dialog to the forum.  The file will be deleted after
you close the dialog.

If this fails you can still use this macro to handle screenshots you
copied to the clipboard using other tools:

Windows snip tool: Window Key + Shift + S
Mac snip tool: Command + Shift + 4
Linux: gnome-screenshot utility

If the macro finds there is already an image copied to the clipboard 
it uses that image instead of bringing up this dialog.  Press Shift
while invoking this macro to bypass the clipboard.  Alternatively,
you can clear the image from the clipboard by copying some text to it.

The Open button will open the file in the system
default application for handling png files, e.g. Paint in windows.  This
can be useful if you wish to annotate the screenshot.  But most of the
time you will simply want to drag and drop the file to the forum, then
Cancel to close the open file dialog afterwards.

If you wish to open the screenshot file with another application, right-click
the file and select open with... option or drag/drop to that other application.

"""
        mb.setWindowTitle("Snip macro v"+str(__version__))
        mb.setDetailedText(details)
        mb.setWindowOpacity(0.85)
        pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Snip_Macro")
        lastX = pg.GetInt("LastX",0)
        lastY = pg.GetInt("LastY",0)
        lastWidth = pg.GetInt("LastWidth",100)
        lastHeight = pg.GetInt("LastHeight",100)
        mb.setGeometry(lastX, lastY, lastWidth, lastHeight)
        mb.setWindowFlags(QtCore.Qt.Tool)
        result = mb.exec_()
        if result != QtGui.QMessageBox.Ok:
            userCanceled = True
        if not userCanceled:
            rect = mb.frameGeometry()
            pg = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Snip_Macro")
            pg.SetInt("LastX", rect.x())
            pg.SetInt("LastY", rect.y())
            pg.SetInt("LastWidth", rect.width())
            pg.SetInt("LastHeight", rect.height())
            QtGui.QApplication.processEvents()
            time.sleep(.5) #give time for dialog to close before taking screenshot
            QtGui.QApplication.processEvents()
            screen = QtGui.QApplication.primaryScreen()
            image = screen.grabWindow(0,rect.x(),rect.y(),rect.width(),rect.height()).toImage()
            if not image:
                raise Exception("Snip Macro Error: Unable to grab screen image\n")
    else:
        QtGui.QMessageBox.critical(QtGui.QMainWindow(),"Unsupported","Your version of Qt is not supported for taking screenshots.\n\
It is recommended to update to a newer version of FreeCAD with Qt5+, but you can still use the macro \
for images already copied to the clipboard.\n\n\
Windows snip tool: Window Key + Shift + S\n\
Mac snip tool: Command + Shift + 4\n\
Linux: gnome-screenshot utility\n")
        userCanceled = True
if not userCanceled:
    dirPath = tempfile.mkdtemp()
    filePath = dirPath + os.path.sep + fname
    image.save(filePath)
    fileName = QtGui.QFileDialog.getOpenFileName(QtGui.QApplication.activeWindow(),
    "Drag the image to the forum, then Cancel will delete the temporary file", dirPath, "PNG (*.png)")
    if fileName[0]:  #user selected Open or double-clicked file
        import subprocess, os, platform
        if platform.system() == 'Darwin':       # macOS
            subprocess.call(('open', fileName[0]))
        elif platform.system() == 'Windows':    # Windows
            os.startfile(fileName[0])
        else:                                   # linux variants
            subprocess.call(('xdg-open', fileName[0]))
        QtGui.QApplication.processEvents() #allow some time for file to open before deleting temp folder and contents
        time.sleep(1)
        QtGui.QApplication.processEvents()
    shutil.rmtree(dirPath)