Changing icon in nested menus - python

I don't think this may be posssible but I had still want to try asking.
In the attached screenshot, I have nested menus.
Is it possible to change the arrow keys icon as 'highlighted' by the red box?
I am trying to change the arrow key to a plus icon if there are no sub menu items found.
The default arrow can be in use if there are sub menu items found.

Yes, you can change the color of right-arrow.
But there is a trick to change it.
The truth of indicator is "branch-closed png file"
You can see the png file at the almost bottom on the page in the link.
So, it can not be solved by the pure-programmic way.
You prepare the picture in advance by yourself.
and please following code in QMenu constructor.
self.setStyleSheet("QMenu::right-arrow{image:url(stylesheet-branch-closed-red.png);}")
Attention:
stylesheet-branch-closed-red.png is my renamed picture.
You can download the original picture from the above link page.
you right-click the png picture and save as name.
This code comes from your past question.
class QCustomMenu(QtGui.QMenu):
"""Customized QMenu."""
def __init__(self, title, parent=None):
super(QCustomMenu, self).__init__(title=str(title), parent=parent)
self.setup_menu()
self.setStyleSheet("QMenu::right-arrow{image:url(stylesheet-branch-closed-red.png);}")
def setup_menu(self):
self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
def contextMenuEvent(self, event):
no_right_click = [QAddAction]
if any([isinstance(self.actionAt(event.pos()), instance) for instance in no_right_click]):
return
pos = event.pos()
def addAction(self, action):
super(QCustomMenu, self).addAction(action)
As the result, it will become like this.
You will dislike the white part of the arrow.
No problem, you can delete them clearly with a free-paint soft, but I didn't do it because it was needless.

Related

Qt Tooltip how to prevent the text from disappearing after the builtin delay?

I have a QGraphicsScene and inside I have a few QGraphicsItems. When I hover over a QGraphicsRectItem, I want to show an overlay text immediately. Only when the cursor leaves the item, then the text can disappear.
Below you can see I tried using whatsthis (which crashes python) and tooltip.
With tooltip, I am able to make the text appear immediately but the text disappears on its own after the built-in delay.
class Node(QGraphicsRectItem):
def __init__(self, x, y, w, h, qpen, qbrush, text):
QGraphicsRectItem.__init__(self)
self.setRect(x, y, w, h)
self.setBrush(qbrush)
self.setPen(qpen)
self.setAcceptHoverEvents(True)
self.text = text
#self.setFlag(QGraphicsItem.ItemIsMovable)
#self.toolkit = QToolTip()
#self.setToolTip(text)
#self.setWhatsThis(self.text)
def hoverEnterEvent(self, event):
QToolTip.showText(event.screenPos(),self.text)
#print("hoverEnterEvent : {}".format(event))
#print(type(self.toolTip))
#self.QToolTip.showText(event.pos(),text)
#event.ToolTip.showText(text)
#QWhatsThis.showText(event.screenPos(),self.text)
#self.enterWhatsThisMode()
def hoverLeaveEvent(self, event):
QToolTip.hideText()
#print("hoverLeaveEvent : {}".format(event))
#self.QToolTip.hideText()
#event.ToolTip.hideText()
#QWhatsThis.hideText()
#self.leaveWhatsThisMode()
I am using python 3.3 and pyside
I thought this SO post and this page might be your answer. But as you point out, a comment at bottom of page indicates this only works for controlling how soon tooltip appears, not how long it remains visible. Unfortunately, that link to bug item no longer exists (see also Keep Qt tooltip open). The closest I found is https://bugreports.qt-project.org/browse/QTBUG-31707 which hasn't been assigned to anyone, which suggests that you either have to find a library that provides what you want or, short of that, you have to implement your own. For the latter, you might want to look at QxtToolTip or example

Custom calendar cell in PyQt

I would like to make a custom cell for PyQt.QtGui.QCalendarWidget. I need to add a short small text to the bottom of some calendar cells, is it possible? If so, could anyone point me in the right direction?
So far the idea is to subclass the QCalendarWidget and override its paintCell method. However I have no idea what to do there. I've tried to look at the Qt and the code of the widget, but it's pretty complex and I didn't find the place where they actualy paint the cell. So I would appreciate any advice.
You don't need to reimplement painting. Just call the default implementation and add text drawing:
class MyCalendar(QtGui.QCalendarWidget):
def __init__(self,parent=None):
QtGui.QCalendarWidget.__init__(self,parent)
def paintCell(self, painter, rect, date):
QtGui.QCalendarWidget.paintCell(self, painter, rect, date)
if date.day() % 5 == 0: # example condition based on date
painter.drawText(rect.bottomLeft(), "test")
You need to set proper height for the widget to ensure that there is enough space in cells to display the text.

Customising location-sensitive context menu in QTextEdit

I am trying to adjust the context menu in a QTextEdit. I have succeeded in getting access to and then displaying the default menu with the following code:
class LinkTextBrowser(QTextBrowser):
def contextMenuEvent(self, event):
menu = self.createStandardContextMenu(event.pos())
# do stuff to menu here
menu.popup(event.globalPos())
However, this does not work for location-sensitive clicks. The case in question is the "Copy Link Location" item in a QTextBrowser's right click menu, which is only enabled if you right click on a link, for obvious reasons. I can't get it to ever be enabled. I suspect I am passing the wrong position to createStandardContextMenu, but I can't figure out the correct position to feed it.
I have tried both event.globalPos() and event.pos(), neither of which work. I also looked at the source code for QTextEdit, but didn't get anywhere. What position is it expecting?
Edit: Update: It appears the problem is the scrolling in the TextBrowser; if I scroll to the top of the window and use event.pos() it behaves. I don't have working code yet, but correcting for the scroll is the solution.
(Specifically, I want to disconnect the signal emitted by the Copy Link Location action and connect it to my own function so I can adjust the URL before copying it to the clipboard, allowing me to make links absolute and so forth before copying, and I have no particular desire to re-write the working bits.)
Here is the working transform of the coordinates:
class LinkTextBrowser(QTextBrowser):
def contextMenuEvent(self, event):
self.link_pos = event.pos()
# correct for scrolling
self.link_pos.setX(self.link_pos.x() + self.horizontalScrollBar().value())
self.link_pos.setY(self.link_pos.y() + self.verticalScrollBar().value())
menu = self.createStandardContextMenu(self.link_pos)
# do stuff to menu
menu.popup(event.globalPos())
Try self.mapToGlobal(event.pos()), it should take into account scroll position.
Maybe you can try something like:
QMenu *menu = new QMenu();
menu->addAction(...);
menu->exec(textEdit->mapToGlobal(pos));
It's C++ but I'm sure that you can easy convert it to python.

PyQt: How to transfer text data between widgets?

So here's my problem. I attached an image of what I'm working with to give you some visual idea of what I'm doing. I have my list of icons at the bottom. I have a QGraphicsView above it (with the line going through it).
http://oi43.tinypic.com/2uhx1xj.jpg (apparently I'm not able to post images yet because I'm a newbie)
So far I am able to drag and drop an icon from the bottom list into the QGraphicsView. However, the image that's dropped into the QGraphicsView is just 1 default image that I defined as the "blender" icon. (The code below is what I have working with 1 default image).
#Defined in QGraphicScene
def dropEvent(self, event):
event.accept()
item = QGraphicsPixmapItem(QPixmap("images/{}".format("blender")))
item.setFlags(QGraphicsItem.ItemIsSelectable|
QGraphicsItem.ItemIsMovable)
position = QPointF(event.scenePos())
print(position)
item.setPos(position)
self.addItem(item)
What I WANT is the image that is dropped into the QGraphicsView to be the same image that is in the QListWidget. For example, if "Mozilla" is dragged and dropped into QGraphicsView I want the Mozilla icon to be displayed, and etc... I think if I can somehow get the text name transferred from the QListWidget to the QGraphicsView then I could just replace "blender" with whatever variable.
What I think I have to do is redefine the "startDrag()" function for my QListWidget and then in my QGraphicsScene, I need to implement my dropEvent() to handle that data. I've looked over QMimeData & QDataStream but am not exactly clear. I think it looks something like this:
#startDrag() that is reimplemented for the listWidget1 function. listWidget1 is the list in the first tab
def scene_startDrag(self, dropActions):
item = self.listWidget1.selectedItems()
data = QByteArray()
stream = QDataStream(data, QIODevice.WriteOnly)
stream.writeQString(item.text())
mimeData = QMimeData()
mimeData.setData("application/x-img", data)
drag = QDrag(self)
drag.setMimeData(mimeData)
If it helps, I have all of those icons in listWidget1 stored in a dictionary called "nodes" with the key being whatever the name is being displayed in the list. So in listWidget1, Mozilla's key is just "mozilla".
So to put it simply, all I want to do is get the correct image to show up in the QGraphicsView. Sorry for the long post. Does anybody have any idea on how I can implement this? Thank you for any input!
Well I didn't think I'd get this one but I figured it out. After reading more extensively about drag/drop functions I got something that works. QMimeData is confusing.
Here's what I did. First re-implemented the startDrag() for the list widget:
def scene_startDrag(self, dropActions):
item = self.listWidget1.currentItem()
data = QByteArray()
stream = QDataStream(data, QIODevice.WriteOnly)
stream.writeQString(item.text())
mimeData = QMimeData()
mimeData.setData("application/x-imgname", data)
drag = QDrag(self)
drag.setMimeData(mimeData)
drag.exec() #actually starts the dragging
Then in the QGraphicsScene that's associated with the QGraphicsView I reimplemented the dropEvent() function:
def dropEvent(self, event):
if(event.mimeData().hasFormat("application/x-imgname")):
event.accept()
data = event.mimeData().data("application/x-imgname")
stream = QDataStream(data, QIODevice.ReadOnly)
text = stream.readQString()
item = QGraphicsPixmapItem(QPixmap("images/{}".format(text)))
item.setFlags(QGraphicsItem.ItemIsSelectable|
QGraphicsItem.ItemIsMovable)
position = QPointF(event.scenePos())
item.setPos(position)
self.addItem(item)

gtk treeview: place image buttons on rows

For each row in my treeview, I want 4 image buttons next to each other. They will act like radio buttons, with only one being activateable at a time. Each button has an 'on' and 'off' image.
How do I do this? I figured out how to put images there, and how to put togglebuttons, but this seems to require some more effort as there is no pre-built cellrenderer that does what I want.
Basically what'd solve my problem is figuring out how to make an image in a gtk.treeview clickable. any ideas?
Have a look at this 'http://www.daa.com.au/pipermail/pygtk/2010-March/018355.html'. It shows you how to make a gtk.CellRendererPixbuf activatable, and able to connect to a click event signal.
cell = CellRendererPixbufXt()
cell.connect('clicked', func)
Update
As pointed out this answer, or the reference given doesn't work as advertised. It's missing the do_activate method, which needs to emit the clicked signal. Once it's done that, then the cell.connect will work.
Sorry if this answer mislead anyone.
Here is a short version without kiwi requirement.
class CellRendererClickablePixbuf(gtk.CellRendererPixbuf):
__gsignals__ = {'clicked': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
(gobject.TYPE_STRING,))
}
def __init__(self):
gtk.CellRendererPixbuf.__init__(self)
self.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE)
def do_activate(self, event, widget, path, background_area, cell_area,
flags):
self.emit('clicked', path)
Here is what worked for me:
class CellRendererClickablePixbuf(gtk.CellRendererPixbuf):
gsignal('clicked', str)
def __init__(self):
gtk.CellRendererPixbuf.__init__(self)
self.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE)
def do_activate(self, event, widget, path, background_area, cell_area, flags):
self.emit('clicked', path)

Categories

Resources