Here's the formulation of the linear program and the Gurobi code to solve it:

**Decision Variables:**

* `x`: Number of paintings to stock
* `y`: Number of photo prints to stock

**Objective Function:**

Maximize profit: `330x + 170y`

**Constraints:**

* **Space Constraint:** `7x + 4y <= 200` (Total wall space used must be less than or equal to 200 sq ft)
* **Budget Constraint:** `400x + 200y <= 7000` (Total cost must be less than or equal to $7000)
* **Photo Print Proportion Constraint:** `y >= 0.2 * (x + y)` (At least 20% of items must be photo prints)
* **Non-negativity Constraints:** `x >= 0`, `y >= 0` (Cannot stock negative quantities)


```python
import gurobipy as gp
from gurobipy import GRB

# Create a new model
m = gp.Model("Art_Gallery")

# Create decision variables
x = m.addVar(vtype=GRB.INTEGER, name="paintings") # Number of paintings
y = m.addVar(vtype=GRB.INTEGER, name="photo_prints") # Number of photo prints

# Set objective function
m.setObjective(330*x + 170*y, GRB.MAXIMIZE)

# Add constraints
m.addConstr(7*x + 4*y <= 200, "space_constraint")
m.addConstr(400*x + 200*y <= 7000, "budget_constraint")
m.addConstr(y >= 0.2 * (x + y), "photo_proportion_constraint")


# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print(f"Optimal Solution Found:")
    print(f"Number of Paintings (x): {x.x}")
    print(f"Number of Photo Prints (y): {y.x}")
    print(f"Maximum Profit: ${m.objVal}")
elif m.status == GRB.INFEASIBLE:
    print("Model is infeasible. No solution exists.")
else:
    print(f"Optimization terminated with status: {m.status}")

```
