How to resize display resolution on windows with nim - nim-lang

I'd like to use nim to resize the default display resolution on a machine (windows 10 only), I want to basically do it via a command line call like setDisplay 1280 1024
I've seen and used the python example Resize display resolution using python with cross platform support which I can follow, but just can't translate. I just don't get how to fill in EnumDisplaySettings
import winim/lean
import strformat
var
cxScreen = GetSystemMetrics(SM_CXSCREEN)
cyScreen = GetSystemMetrics(SM_CYSCREEN)
msg = fmt"The screen is {cxScreen} pixels wide by {cyScreen} pixels high."
EnumDisplaySettings(Null,0, 0) #total type mismatch
MessageBox(0, msg, "Winim Example Screen Size", 0)
Tried checking stuff like https://cpp.hotexamples.com/fr/examples/-/-/EnumDisplaySettings/cpp-enumdisplaysettings-function-examples.html but wasn't much help, same for https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-changedisplaysettingsa

I wrote about 2% of this answer myself, and the rest came from pointystick on discord - thanks to them!
The solution is a bit lazy, but it's so fast that for most that won't matter.
With no cmd line args it will just set the display to the default recommendation, else with 2 cmd line args it can reset your display if it finds a match
import winim/lean
import os
import strutils
var modeToFind = (width: 1920, height: 1080, bitsPerPixel: 32,
refreshRate: 60)
var reset = 0
type ModeNotFoundError = object of CatchableError
proc getDisplayMode(): DEVMODEW =
## Finds the wanted screen resolution or raises a ModeNotFoundError.
var
nextMode: DWORD = 0
mode: DEVMODEW
while EnumDisplaySettings(nil, nextMode, mode) != 0:
echo $mode.dmPelsWidth & " x " & $mode.dmPelsHeight &
" x " & $mode.dmBitsPerPel &
" - " & $mode.dmDisplayFrequency
inc nextMode
if (mode.dmPelsWidth == modeToFind.width) and
(mode.dmPelsHeight == modeToFind.height):
echo "Found it!"
return mode
if(reset==1):
return mode
raise newException(ModeNotFoundError, "Cannot find wanted screen mode")
proc changeResolution(): bool =
## Actually changes the resolution. The return value indicates if it worked.
result = false
try:
let wantedMode = getDisplayMode()
result = ChangeDisplaySettings(wantedMode.unsafeAddr, 0.DWORD) == DISP_CHANGE_SUCCESSFUL
except ModeNotFoundError: discard
when isMainModule:
var
cxScreen:int32 = 0 #= GetSystemMetrics(SM_CXSCREEN)
cyScreen:int32 = 0 # = GetSystemMetrics(SM_CYSCREEN)
try:
cxScreen = (int32) parseInt(paramStr(1))
cyScreen = (int32) parseInt(paramStr(2))
modeToFind.width = cxScreen
modeToFind.height = cyScreen
except:
reset = 1
if not changeResolution():
echo "Change Resolution Failed"

Related

Error inserting an email string in sqlite3 and python Tkinter

I am writing a simple program to update a basic db based on data entered on a simple GUI. I'm using string formatting but keep getting an error trying to enter an email address , which I know should be surrounded with double-quotes. I'm sure the solution is simple- I just don't know what it is!
def update_rec():
# Connect to the db
conn = sqlite3.connect("address_book.db")
# create a cursor
c = conn.cursor()
fields = ["f_name", "s_name", "mob", "email"]
# Check which textboxes have data
update_txt = ""
update_field = ""
rec_no = str(id_no.get())
if len(f_name.get()) > 0:
update_txt = f_name.get()
update_field = fields[0]
elif len(s_name.get()) > 0:
update_txt = s_name.get()
update_field = fields[1]
elif len(mob.get()) > 0:
update_txt = mob.get()
update_field = fields[2]
elif len(email.get()) > 0:
update_txt = email.get()
update_field = fields[3]
else:
update_txt = ""
update_field = ""
c.execute("""UPDATE address_book SET {0} = ? WHERE {1} = ?""".format(update_field, update_txt), rec_no)
conn.commit()
conn.close()
I keep getting this error:
c.execute("""UPDATE address_book SET {0} = ? WHERE {1} = ?""".format(update_field, update_txt), rec_no)
sqlite3.OperationalError: near "#gmail": syntax error
What needs to be supplied to .format() is getting confused with what needs to be passed to c.execute().
Do it in two steps so it's easier to understand.
You need to tell us what rec_field should be. It's probably something like id or address_book_id or ?
rec_field = 'id' # you know what this should be...
qry = """UPDATE address_book
SET {0} = ?
WHERE {1} = ?;""".format(update_field, rec_field)
c.execute(qry, (update_txt,rec_no))

Why doesn't my font.name property affect the fonts on ppt made using Python-pptx? I always get arial font

So I'm trying to write some program to convert html to pptx using Python.
I'm using some code to parse through the file and then format text at run level.
I am using 2 textframes on a blank slide to work, the first textframe is used for title and 2nd one is used for rendering the body of html.
But no matter what I do (Paragraph.font.name or run.font.name), I am always getting Arial font in my 2nd textframe.
I've tried to update the fontnames by looping over tf.paragraphs and also by looping over all runs (paragraph.runs) nothing seems to work.
Here is my function which I use for setting the font
def setFont(font,tags,fontStyle,size):
font.language_id = MSO_LANGUAGE_ID.HEBREW
font.size = Pt(size)
font.name = fontStyle
for tag in tags:
if tag == 'b':
font.bold = True
elif tag == 'i':
font.italic = True
elif tag == 'u':
font.underline = True
return font
and here is my main calling function (I've removed some other calls which are not directly related to python-pptx)
def makeSlide(prs,title,body,fontStyle,titleSize,bodySize):
#Add title Slide
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
width = height = Inches(8)
txBox = slide.shapes.add_textbox(Inches(1), Inches(0.5), Inches(8), Inches(1))
tf = txBox.text_frame
tf.text = title
tf.paragraphs[0].font.size=Pt(titleSize)
tf.paragraphs[0].font.bold = True
tf.paragraphs[0].font.color.rgb = RGBColor(255,0,0)
tf.paragraphs[0].font.name = fontStyle
tf.paragraphs[0].alignment = PP_ALIGN.CENTER
styles = MY_CUSTOM_HTML_BODY_PARSER() #Removed this part from here, its just a parser which gives output in a desired format
#Start 2nd textbox for body
txBox2 = slide.shapes.add_textbox(Inches(0.5), Inches(1.7), Inches(9), Inches(5.5))
tf = txBox2.text_frame
tf.clear()
tf.word_wrap = True
tf.paragraphs[0].text = ''
tf.paragraphs[0].font.name = fontStyle
paragraph = tf.add_paragraph()
paragraph.alignment = alignment
#Loop over styles (Tag info and render pptx accordingly)
new_line = True
level = 0
number = 0
for _ in styles:
#Can ignore this part, I'm just checking to see if I have to go on a new line or not
if _ == '\n':
paragraph = tf.add_paragraph()
paragraph.alignment = alignment
new_line = True
else:
tags = _[1]
#Can also ignore this, I'm checking to see if I have to be on next level in lists or not
#(I use custom bullet function, since python-pptx doesn't have a function for numbered bullets.
if _[1].count('ul') > 1 or _[1].count('ol') > 1 or _[1].count('ul') + _[1].count('ol') > 1:
level = 1
if new_line:
paragraph.level = level
level = 0
else:
paragraph = tf.add_paragraph()
paragraph.alignment = alignment
paragraph.level = level
level = 0
new_line = True
if new_line:
run = paragraph.add_run()
#Custom bullet function as u can see I send in fontStyle here and apply style inside function
run,number = addBullets(run,tags,bodySize-3,number,fontStyle)
new_line = False
run = paragraph.add_run()
run.text = parser.words_styles[_[0]][0]
font = run.font
#SetFont function Defined above
font = setFont(font,tags,fontStyle,bodySize)
new_line = False
for paragraph in tf.paragraphs:
paragraph.font.name = fontStyle
for run in paragraph.runs:
if run.font.name != fontStyle:
print(run.text)
#return slide
return slide
I'm not quite sure where I am doing wrong, would appreciate any help, I can clean up code more if that's needed.

How to pick out the second to last line from a telnet command

like the many other threads I've opened, I am trying to create a multi-feature instant replay system utilizing the blackmagic hyperdeck which operates over Telnet. The current feature I am trying to implement is an in-out replay which requires storing two timecode variables in the format of hh:mm:ss;ff where h=hours, m=minutes, s=seconds, and f=frames #30fps. the telnet command for this is transport info, and the response returns 9 lines of which I only want the timecode from the 7th. Any idea on how to do this, as it is way out of my league?
status: stopped
speed: 0
slot id: 1
clip id: 1
single clip: false
display timecode: 00:00:09;22
timecode: 00:00:09;22
video format: 1080i5994
loop: false
Here's ideally what I would like it to look like
import telnetlib
host = "192.168.1.13" #changes for each device
port = 9993 #specific for hyperdecks
timeout = 10
session = telnetlib.Telnet(host, port, timeout)
def In():
session.write(b"transport info \n")
line = session.read_until(b";00",.5)
print(line)
#code to take response and store given line as variable IOin
def out():
session.write(b"transport info \n")
line = session.read_until(b";00",.5)
print(line)
#code to take response and store given line as variable IOout
def IOplay():
IOtc = "playrange set: in: " + str(IOin) + " out: " + str(IOout) + " \n"
session.write( IOtc.encode() )
speed = "play: speed: " + str(Pspeed.get() ) + "\n"
session.write(speed.encode() )
For the most part here's what I got to at least partially work
TCi = 1
TCo = 1
def In():
global TCi
session.write(b"transport info \n")
by = session.read_until(b";00",.5)
print(by)
s = by.find(b"00:")
TCi = by[s:s+11]
def Out():
global TCo
session.write(b"transport info \n")
by = session.read_until(b";00",.5)
print(by)
s = by.find(b"00:")
TCo = by[s:s+11]
def IOplay():
IOtc = "playrange set: in: " + str(TCi) + " out: " + str(TCo) + " \n"
print(IOtc.encode() )
session.write(IOtc.encode() )
speed = "play: speed: 2 \n"
session.write(speed.encode() )
except that its encoding as
b"playrange set: in: b'00:00:01;11' out: b'00:00:03;10' \n"
rather than
"playrange set: in: 00:00:01;11 out: 00:00:03;10 \n"
I need to get rid of the apostrophe's and b prefix in front of the variables
Any ideas?
def get_timecode(text):
tc = ''
lines = text.split('\r\n')
for line in lines:
var, val = line.split(': ', maxsplit=1)
if var == 'timecode':
tc = val
return tc
You could choose to go directly to lines[6], without scanning,
but that would be more fragile if client got out of sync with server,
or if server's output formatting changed in a later release.
EDIT:
You wrote:
session.write(b"transport info \n")
#code to take response and store given line as variable IOin
You don't appear to be reading anything from the session.
I don't use telnetlib, but the docs suggest you'll
never obtain those nine lines of text if you don't do something like:
expect = b"foo" # some prompt string returned by server that you never described in your question
session.write(b"transport info\n")
bytes = session.read_until(expect, timeout)
text = bytes.decode()
print(text)
print('Timecode is', get_timecode(text))

python3 and libre office calc - setting column width

I am using pyoo to generate reports as open document spreadsheets. pyoo can do everything I require bar setting column widths. Some I want to set as a constant, others as optimal width. From the pyoo website (https://github.com/seznam/pyoo): "If some important feature missing then the UNO API is always available."
A few hours of Googling got me to the class com.sun.star.table.TableColumn which from this page appears to have the properties ("Width" and "OptimalWidth") that I require, but -
>>> x = uno.getClass('com.sun.star.table.TableColumn')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/uno.py", line 114, in getClass
return pyuno.getClass(typeName)
uno.RuntimeException: pyuno.getClass: uno exception com.sun.star.table.TableColumn is unknown
I have no idea whatsoever how to get this to work. The documentation for UNO is overwelming to say the least...
Any clues would be enormously appreciated.
Example Python-UNO code:
def resize_spreadsheet_columns():
oSheet = XSCRIPTCONTEXT.getDocument().getSheets().getByIndex(0)
oColumns = oSheet.getColumns()
oColumn = oColumns.getByName("B")
oColumn.IsVisible = False
oColumn = oColumns.getByName("C")
oColumn.Width = 7000
oColumn = oColumns.getByName("D")
oColumn.OptimalWidth = True
Documentation:
https://wiki.openoffice.org/wiki/Documentation/BASIC_Guide/Rows_and_Columns
https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Columns_and_Rows
EDIT:
From the comment, it sounds like you need to work through an introductory tutorial on Python-UNO. Try http://christopher5106.github.io/office/2015/12/06/openoffice-libreoffice-automate-your-office-tasks-with-python-macros.html.
Thank you Jim K, you pointed me in the right direction, I got it working. My python script generates a ten sheet spreadsheet, and manually adjusting the column widths was becoming a pain. I post below my final code if anyone wants to comment or needs a solution to this. It looks like a pigs breakfast to me combining raw UNO calls and pyoo, but it works I guess.
#! /usr/bin/python3.6
import os, pyoo, time, uno
s = '-'
while s != 'Y':
s = input("Have you remembered to start Calc? ").upper()
os.system("soffice --accept=\"socket,host=localhost,port=2002;urp;\" --norestore --nologo --nodefault")
time.sleep(2)
desktop = pyoo.Desktop('localhost', 2002)
doc = desktop.create_spreadsheet()
class ofic:
sheet_idx = 0
row_num = 0
sheet = None
o = ofic()
uno_localContext = uno.getComponentContext()
uno_resolver = uno_localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", uno_localContext )
uno_ctx = uno_resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
uno_smgr = uno_ctx.ServiceManager
uno_desktop = uno_smgr.createInstanceWithContext( "com.sun.star.frame.Desktop", uno_ctx)
uno_model = uno_desktop.getCurrentComponent()
uno_controller = uno_model.getCurrentController()
uno_sheet_count = 0
for i in range(5):
doc.sheets.create("Page {}".format(i+1), index=o.sheet_idx)
o.sheet = doc.sheets[o.sheet_idx]
o.sheet[0, 0].value = "The quick brown fox jumps over the lazy dog"
o.sheet[1, 1].value = o.sheet_idx
uno_controller.setActiveSheet(uno_model.Sheets.getByIndex(uno_sheet_count))
uno_sheet_count += 1
uno_active_sheet = uno_model.CurrentController.ActiveSheet
uno_columns = uno_active_sheet.getColumns()
uno_column = uno_columns.getByName("A")
uno_column.OptimalWidth = True
uno_column = uno_columns.getByName("B")
uno_column.Width = 1350
o.sheet_idx += 1
doc.save("whatever.ods")
doc.close()

(WinApi) ChangeDisplaySettingsEx does not work

I'm trying to write a python script to switch the primary monitor.
I have 3 Monitors (one is plugged into my i5's graphics chip, and 2 are plugged into a ATI HD7870)
I wrote the following script:
import win32api as w
import win32con as c
i = 0
workingDevices = []
def setPrimary(id):
global workingDevices
return w.ChangeDisplaySettingsEx(
workingDevices[id].DeviceName,
w.EnumDisplaySettings(
workingDevices[id].DeviceName,
c.ENUM_CURRENT_SETTINGS
),
c.CDS_SET_PRIMARY | c.CDS_UPDATEREGISTRY | c.CDS_RESET) \
== c.DISP_CHANGE_SUCCESSFUL
while True:
try:
Device = w.EnumDisplayDevices(None, i, 1)
if Device.StateFlags & c.DISPLAY_DEVICE_ATTACHED_TO_DESKTOP: #Attached to desktop
workingDevices.append(Device)
i += 1
except:
break
print("Num Devices: ", len(workingDevices))
for dev in workingDevices:
print("Name: ", dev.DeviceName)
Invoking it leads to:
In [192]: %run test.py
Num Devices: 3
Name: \\.\DISPLAY1
Name: \\.\DISPLAY2
Name: \\.\DISPLAY7
In [193]: setPrimary(0)
Out[193]: True
In [194]: setPrimary(1)
Out[194]: True
In [195]: setPrimary(2)
Out[195]: True
So far it looks great, but the problem is: nothing changes. My monitors flicker shortly because of the CDS_RESET but the primary screen does not change, although ChangeDisplaySettingsEx returns DISP_CHANGE_SUCCESSFUL
Does anyone have an Idea why?
(I use Python 3.5.1 and PyWin32 build 220)
PS I use 1 as the third arg for EnumDisplayDevices because the msdn states it should be set to one, although the PyWin help says it should be set to 0.
But the behaviour of the script does not change independent of this value beeing one or zero
Ok, I found the solution.
Apperantly the primary monitor must always be at position (0, 0).
So when I tried to set another monitor to primary its position was set to (0, 0) which caused it to intersect with the old primary one.
It seems the way to go is to update the positions of all Monitors, and write those changes to the registry, and then once this is done apply the changes by calling ChangeDisplaySettingsEx() with default parameters.
This is my new (now working) code:
import win32api as w
import win32con as c
def load_device_list():
"""loads all Monitor which are plugged into the pc
The list is needed to use setPrimary
"""
workingDevices = []
i = 0
while True:
try:
Device = w.EnumDisplayDevices(None, i, 0)
if Device.StateFlags & c.DISPLAY_DEVICE_ATTACHED_TO_DESKTOP: #Attached to desktop
workingDevices.append(Device)
i += 1
except:
return workingDevices
def setPrimary(id, workingDevices, MonitorPositions):
"""
param id: index in the workingDevices list.
Designates which display should be the new primary one
param workingDevices: List of Monitors returned by load_device_list()
param MonitorPositions: dictionary of form {id: (x_position, y_position)}
specifies the monitor positions
"""
FlagForPrimary = c.CDS_SET_PRIMARY | c.CDS_UPDATEREGISTRY | c.CDS_NORESET
FlagForSec = c.CDS_UPDATEREGISTRY | c.CDS_NORESET
offset_X = - MonitorPositions[id][0]
offset_Y = - MonitorPositions[id][1]
numDevs = len(workingDevices)
#get devmodes, correct positions, and update registry
for i in range(numDevs):
devmode = w.EnumDisplaySettings(workingDevices[i].DeviceName, c.ENUM_CURRENT_SETTINGS)
devmode.Position_x = MonitorPositions[i][0] + offset_X
devmode.Position_y = MonitorPositions[i][1] + offset_Y
if(w.ChangeDisplaySettingsEx(workingDevices[i].DeviceName, devmode,
FlagForSec if i != id else FlagForPrimary) \
!= c.DISP_CHANGE_SUCCESSFUL): return False
#apply Registry updates once all settings are complete
return w.ChangeDisplaySettingsEx() == c.DISP_CHANGE_SUCCESSFUL;
if(__name__ == "__main__"):
devices = load_device_list()
for dev in devices:
print("Name: ", dev.DeviceName)
MonitorPositions = {
0: (0, -1080),
1: (0, 0),
2: (1920, 0)
}
setPrimary(0, devices, MonitorPositions)

Resources