How can I customize the appearance of the actions in my QToolBar? - qt

I have just changed some toolbars from Q3ToolBars (with QToolButtons explicitly added to them) into Q4 toolbars (with actions added to them straight away instead.)
The old tool buttons had a nice outline around them, but this is not displayed in the new version; the QActions in the Q4 toolbar just look like a line of icons. Is there a way to change the 'button' style in the new version (assuming these actions can be considered as such) and give them the outline? I've looked through the QToolBar reference, but the toolButtonStyle() function only appears to work with whether you want to display icon, text, etc.
...Or will I have to just make actual tool buttons and/or QPushButtons and use addWidget()?

The widget associated with a given action is accessible through QToolBar::widgetForAction (since Qt 4.2). So, you can pass your actions to this method, get the QWidgets returned by it, convert them to QToolBar, and handle them like you normally would (code not tested):
// ...
auto toolButton =
static_cast<QToolButton *>(
m_ui.toolbar->widgetForAction(m_ui.my_Action));
// Will make the toolButton always appear raised:
toolButton->setAutoRaise(false);
// ...
As far as I've been testing, some methods might not work (i.e., QWidget::hide), so do your own testing.

Yes, of course you can edit look of QToolButtons in two different ways:
You can set it style sheet using void QWidget::setStyleSheet(const QString &)
You can reimplement QToolButtons class with new paintEvent function where you will be able to exactly set how your button should looks like.

Related

What's the NSView version of NSCell's highlighted property?

I'm migrating a cell-based NSTableView to be view-based. With NSCell, to determine if a cell was highlighted (e.g., to draw the text in white instead of black), I looked at the NSCell highlighted property.
What's the NSView version of this? I can't find anything like this in the docs.
The easiest way to do this is to simply subclass NSTableCellView. All the documentation says that you can subclass either NSTableCellView or NSView, e.g., Table View Programming Guide for Mac:
Drag an NSTableCellView object (or a custom view) from the object library to the appropriate column in the table view. ... Typically, the view class is a subclass of NSTableCellView.
It doesn't say what this is, or why you'd want to use it. It looks like an NSView which has an NSTextField and an NSImageView, and that's it -- so if you're not making a view that has these, it's tempting to ignore this class and just subclass NSView.
Interestingly, though, if you have any NSTextFields in an NSTableCellView (even if you don't use the textField property for this!), they automatically use the correct light/dark coloring.
In particular, it seems that the backgroundStyle property of NSTableCellView is what causes the text value to actually change. The documentation says:
The default implementation automatically forwards calls to all subviews that implement setBackgroundStyle: or are an NSControl, which have NSCell classes that respond to setBackgroundStyle:.
NSTextField is an NSControl with an NSCell, of course, so it gets this called on it.
While it's not exactly clear in Apple's documentation (what does "this" refer to?), it seems that NSTableView calls -setBackgroundStyle: on any view that defines it. So if you don't want to subclass NSTableCellView, you can alternatively just add a property to your own NSView:
var backgroundStyle: NSBackgroundStyle
and have your drawing code use that.

Paste event in Qt

I want to build a structured document editor using Qt. The base concept for v1 is nested sections, each section having a title and one or more paragraphs. Sections and paragraphs are distinct visual units (probably via background shading). I also need to be able to store character-level semantics (ie: this run of text is associated with reference X). If I wanted to build a read-only view of this it would be doable with QFrame for the sections and a QLabel for each title and each paragraph. To make this editable I'm pretty sure I can capture all keyboard events to the window and implement a cursored text-entry-and-editing feel that way.
What I'm having trouble with is how to handle copy/paste.
I want the clipboard interactions to feel native: that is, ctrl+c/v on window, command+c/v on OSX, ctrl+c/v for clipboard on X, select to copy for PRIMARY on X, middle click to paste for PRIMARY on X, etc.
The standard text editing controls in Qt handle all of this just fine. I'm wondering if there is some sort of "paste event" or similar that I can grab to implement the same thing in my custom widget? Is there another way?
For native keyboard shortcuts, you can add them to menu items:
ui->actionCut->setShortcut(QKeySequence::Cut);
ui->actionCopy->setShortcut(QKeySequence::Copy);
ui->actionInsert_empty_row->setShortcut(Qt::Key_Insert);
ui->actionPaste->setShortcut(QKeySequence::Paste);
ui->actionRemove->setShortcut(QKeySequence::Delete);
See QKeySequence docs
There's no paste signal/event as far as i know to listen to, though there's nothing stopping you from taking a sneak look at how the paste() slot is implemented in widgets like QLineEdit and implement your own if possible. The afferent signal is not that important, since it's just a signal and you can trigger that whenever you desire(eg. Ctrl+v, context menu or program menu).
LE: If i think better, you might be thinking this the wrong way, you don't need a signal, you just need the slot that you can call whenever the action is called by any means you wish(eg. ctrl+v). Once you have the slot(QClipboard), it's just a matter of properly connecting it to the desired triggering actions/signals.
I'm not completely sure why you would want to do it with a QLabel and then capture the keys when there are already classes that handle text edition for you (and you can even override the key pressed funcionality)
If you want to have editable text, you could use a QTextEdit or a QPlainTextEdit and those classes already handle the copy-paste functionality (even with right click menu and everything).
If you want to add special a special behavior to your copy and paste, you can override the Mime functions:
//in your header file, add
void insertFromMimeData(const QMimeData *source) override; // override for paste
QMimeData * createMimeDataFromSelection() const override; // override for copy
// in the cpp:
//it would be something like this:
void YourTextField::insertFromMimeData(const QMimeData *source) {
// Do something special on the paste event, maybe even create your own "source"
//call the base class insert
QPlainTextEdit::insertFromMimeData(source);
}
Note: I'm not 100% with the copy, since I only overrode paste, but I'm almost certain that that's the right function.

Qt: Adding a special item to QMenu

Some programs like Maya and Wings3D have a menu, which includes a special link on some menu items on the right side (usually a square) that triggers a different feature. For example, Wings3D might have an item called "Cube", which makes a standard cube. However, if you click on the highlightable/selectable box beside the "Cube" item, it will perform a different operation. I attached an image of the Wings3D example.
Is this an easy way to do this using QMenu and QAction? Should I create a special layout for the QMenu or do I need to subclass it to get more fine-grained control?
You could try using QWidgetAction to accomplish this. But it might take a bit of work to ensure that those actions stay consistent in terms of the look & feel with the typical rendering of QActions across different platforms and styles.

how can I have more than a UI for a QMainWindow?

I would like to have a QMainWindow that can change it's look at runtime, i.e when a user clicks a button. Besides keeping references to different UI classes generated by the QtDesigner, is there another way of doing that? Maybe by storing each UI in a layout ? What do you think ?
How much of the main window do you want to change? You could use a QStackWidget any place you want to change things, and change the shown page of the widget when the button is pressed. This will be quick to change, but for large or complicated UIs it may be slightly slower at startup, since it will be creating the widgets for both UIs at the same time. (There are fairly easy ways to change this, also, but they do add complications to something that could be straightforward for most people.) Also, if both layouts should have the same data, just in different places, you have the additional overhead of keeping both sets of UIs up to date while the program is running.
I think I got it now.
You have a QMainWindow and when a certain event is triggered you want to change the appearance of that particular window, like remove some buttons, add a treeview widget or what not.
Well the straight forward approach would be to do it manually, remove some widgets and add new ones using regular C++ code. This can be abit hard if you're used to Qt Designer.
The other way I can think of is using Qt Designer to generate the code for the other appearances and copy it to a special function. The code generated by Qt Designer is usually in a header file called "ui_classname.h" and isn't hard to understand. You will however need to remove some of it as not all would be necessary.
Also, instead of copying the generated code from Qt Designer you could just call it. Usually your widget has a pointer to the generated class and in your widget's constructor you see something like this:
MyWindow::MyWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::MyWindow)
{
m_ui->setupUi(this);
}
and in the corresponding header file:
class MyWindow : public QMainWindow {
...
private:
Ui::MyWindow *m_ui;
};
You could add the additional generated classes for the other appearances and use them when your event triggers.
It might look like this:
class MyWindow : public QMainWindow {
...
private:
void changeAppearance(int id);
Ui::MyWindow *m_ui;
Ui::MyWindowFirstAppearance *m_uiFirst;
Ui::MyWindowSecondAppearance *m_uiSecond;
...
};
void MyWindow::changeAppearance(int id)
{
// some code to remove the current appearance, basically the opposite of what setupUi is doing
if (id == 0)
m_ui->setupUi(this);
else...
m_uiFirst->setupUi(this);
...
}
This has the benefit of using the generated classes directly, so every change you do in Qt Designer doesn't require a change to your main window. The problem is I'm not sure if it's legal to call setupUi more than once and in a place other than your widget's constructor, so you'll have to check that (by looking at what's happening in the setupUi function).
You can dynamically load UI layouts at runtime. Check Qt documentation for QUiLoader class.
This also enables you to upgrade UI layouts without modifying a single line of code.
What I do is to design two UIs under two different QFrames, put the two QFrames in a layout together in the QMainWindow, and then hide() and show() the correct QFrame that you want...
You can use a QTabWidget and hide its buttons. You can then design each GUI in a separate window of the tabWidget. It has the advantage over hiding frames that you won't clutter up your Qt Creator window.
If I'm getting this right, I think you might want to take a loot at style sheets. It allows you to have "skins" for your widgets, much like CSS.
If I didn't get this right, and what you're trying to do is generate .ui files on the fly and create widgets with those using QUiLoader, then you're probably going at this the wrong way since I can't think of a good reason a regular application would need that.

Flex: Modify an embedded icon and use it in a button?

Just that, if you embed an icon:
[Embed(source='icons/checkmark.png')]
private static var CheckMark:Class;
You end up with a dynamic class. You can pretty easily assign the icon to a button at runtime by calling the setStyle method:
var btn:Button = new Button();
btn.setStyle("icon", CheckMark);
But what if you wanted to alter the icon at runtime, like changing it's alpha value or even redrawing pixels, before assigning it to the button?
So far I can't find a satisfactory answer...
This is the only answer I could find that seemed close: Dynamic Icons (example with View Source)
His solution involves a custom "DynamicIcon" class which is used in the button's icon setting, and a custom Button class which adds one method to the Button class to draw dynamic icons.
The end result is that you are able to send BitmapData to the DynamicIcon class, which will show up in the button. So, embed your image, instantiate your asset class, get the bitmapasset and modify it however you need to and send the bitmapData to the icon.
It's an interesting problem and it seems like there should be an easier solution, but this works without a lot of hassle.
The way I'd solve this is to implement a programmatic skin class that draws the icon itself manually. There's probably more work you'll have to do to ensure the button calculates the correct size as if it has an icon even though it doesn't. You may have to poke through the Button source code to look at how the reference to the icon is stored.
I love just creating programmatic skins that do exactly what I want and then using interesting CSS declarations to modify states - for instance:
button.setStyle("customIconAlpha", .4);
and then of course the skin or the custom button class would have:
var alpha:Number = getStyle("customIconAlpha") as Number;
(not sure if you have to typecast that one)
The big problem I found with programmatic skins is that the button refuses to measure the width/height. I easily got around this by overriding the get methods for each:
override public function get width():Number { return WIDTH; }
override public function get height():Number { return HEIGHT; }
In my case I needed to modify buttons in a TabNavigator, hence no easy way to subclass the button. Thankfully, the parent of each skin is the button, so using static methods within your skin, you can identify the instance of the Button to which the icon skins belong.
If you're using the cover-all "icon" style, a new skin object will be created for each state. So you'll need to keep this in mind when changing the state of the icons.

Resources