NSStatusItem setTitle is ignored on Yosemite - c++

I've been working on a new feature for Mac support in Qt. Basically, it's about adding a NSStatusItem::title() support. Since Qt is a C++ framework, I am working in scope of ObjC-binding (corresponding method is declared in C++ header and defined in .mm source file).
void QCocoaSystemTrayIcon::updateTitle(const QString &title)
{
NSString *nstitle = title.toNSString();
[trayItem setTitle: nstitle];
}
Note: in the code above, toNSString() creates & releases a proper NSString* in place.
Interesting, if you replace actual setting line with
[[trayItem view] setToolTip: nsstring];
tool tip, in fact, is being changed. It proves that trayItem and nsstring are proper objects.
I am running IIRC latest OS X Yosemite 10.10.1

Almost all NSStatusItem methods are deprecated in Yosemite because of the new vibrancy features. Nice description here, NSStatusItem change image for dark tint

The fact that [trayItem view] returns a valid object suggests that you or Qt is setting a custom view.
Once you set a custom view on a status item, setting the title has no effect. (This was true even before these methods were deprecated).
A standard status item (no set custom view) can have its image and title set and have that be forwarded onto the implicitly created button. This was made more explicit/obvious in 10.10 in that those status item properties were deprecated, and you set the button's properties directly.

Related

How to load multiple font of same familiy

I am writing an application using the Qt framework. In the display, I have to show multiple information, but using different types of font of the same family, Montserrat.
What I have done so far to load the fonts is:
int ultralightid = QFontDatabase::addApplicationFont(":/Montserrat_UltraLight.tff");
QString UltraFont= QFontDatabase::applicationFontFamilies(ultralightid ).at(0);
QFont font1(UltraFont,QFont::Normal);
font1.setPixelSize(50);
int lightid = QFontDatabase::addApplicationFont(":/Montserrat_Light.tff");
QString LightFont= QFontDatabase::applicationFontFamilies(lightid).at(0);
QFont font2(LightFont,QFont::Normal);
font2.setPixelSize(150);
label1->setFont(font1);
label2->setFont(font2);
label1->setText("bla bla");
label2->setText("bla bla");
The font sizes are correct, but the font itself it is not. From what I have noticed (trying with Hairline_Montserrat,Light_Montserrat,UltraLight_Montserrat), it is as if the fonts have a sort of priority. If I declare them all, all the fonts are the Light one, if I comment that font type, all of them are Hairline one, otherwise (last priority) the labels use the ultralight font.
I have tried adding other font type (from other families) and in that case my code works correctly.
If I use
qDebug()<<QFontDatabase::applicationFontFamilies(ultralightid);
qDebug()<<QFontDatabase::applicationFontFamilies(lightid);
both of them print the family "Montserrat".
I use the qrc file and the AUTORCC flag in the CMAKE (it should be similar using qmake) and all the file are uploaded correctly.
Do you know if there is another way to add fonts of the same family? Or is there something I am doing wrong?
Here are the fonts:
https://www.onlinewebfonts.com/download/9d31c906a6cc6064bbe7d33d51058317 light
https://it.allfont.net/download/montserrat-light/ ultralight
This is an old question but I was just struggling with exactly the same problem when trying to load normal, bold, ... versions of a font family in Qt.
I solved the problem (although in a somewhat hacky way) by simply giving each of the ttf files a different family name. I used Typograf, simply open the font, right click to open properties and then click rename. There are probably many other tools that do this too.
You don't need to manage font files from one family separatelly.
I suggest this solution:
Create a folder with all ttf's of the same family.
Load all files from the folder via id = QFontDatabase.addApplicationFont(path)
Collect all font families from these files via QFontDatabase.applicationFontFamilies(id)
Check if only one and desired family is loaded, and the family name is exactly the same as requested, or warn the user about these errors.
Create font object font = QFont(family)
Then for example, font.setItalic(True). If Italic version of family is loaded, it will be used, otherwise it will be created from Regular by QT.

How does Qt select a default style?

In a Qt GUI application, QApplication::style()->objectName() will return the current style, for example "windowsvista".
How/where does it choose this default style, and what information does it use to decide?
Qt comes with builtin styles, these are (on my 5.9.2):
Windows
WindowsXP
WindowsVista
Android
Fusion
Macintosh
each one having its own class, derived from QStyle.
To see which ones are available (it depends on Qt build configuration):
const auto & styles = QStyleFactory::keys();
for(const auto & s : styles)
{
qDebug() << s;
}
Custom plugins (i.e. libraries in the QTDIR/plugins/styles directory) would be shown as well, if present.
How the default style is chosen?
Default style is searched in QApplication method style(), in qapplication.cpp file, in this order:
The style override, if set by the environment variable QT_STYLE_OVERRIDE (this is set in QApplicationPrivate::process_cmdline());
The style returned by QApplicationPrivate::desktopStyleKey() (this method loads a list of styles from the current platform theme and select the first name from this list that is present in the QStyleFactory::keys() list);
The first item in QStyleFactory::keys() list.
If a style could not be determined, the function will assert
Q_ASSERT(!"No styles available!");
In the documentation:
Qt contains a set of QStyle subclasses that emulate the styles of the
different platforms supported by Qt (QWindowsStyle, QMacStyle etc.).
You can set the style by using a key: windowsvista for example, fusion, macintosh, etc. When using any key, the style returned will be a subclass of QStyle. Depending on the platform you're using, you will have access to a certain number of keys.
How/where does it choose this default style
It is done in the QStyleFactory source file. You can also take a look a the QStyle source file to get a hang of what's going on.
what information does it use to decide
The default style is platform dependent, and then you can choose any style among the keys at your disposition on this platform.

In iOS how do I change the text of a button, from a class other than viewController?

I would like to change the text of my UIBarButtonItem from another class (objective-C++) that I use in my project.
I have an IBOutlet myButton setup in myViewController and I can successfully do something like:
[ myButton setTitle:#"newTitle" ];
in myViewController.mm
Now I would like to do the same but from myCppClass that I use in my project.
Is there a way for myCppClass to access myViewController's myButton?
Shall I use some type of delegation mechanism?
I am pretty new to Ios and objective-C.
Thanks,
Baba
Create a method within your myViewController class to change the button title, then call that method from myCppClass by following the instructions described in this answer:
How to call method from one class in another (iOS)
https://stackoverflow.com/a/9731162/2274694
The short answer is, don't. You should treat a view controller's views as private. Instead, add a method to your VC like changeButtonTitle. Then call that method from from your other class.
The answers above are correct, but from your comments I suspect you aren't yet happy.
If you are super lazy, and you don't mind the string being the same in all instances of the VC (which in practice is usually the case) you could simply write a getter and setter for the string name as a class variable in the destination class. That way you don't even need access to the actual instance of the class, just its name. Tacky but super easy.
As others have pointed out, don't try and modify the buttons on a different VC directly. Pass a message and have the owning VC do it when it loads.
Well, passing messages forwards (to a new VC) is very easy. At the bottom of every VC class code there is #pragma navigation section commented out which gives you a handle to the destination VC. Cast it to the proper type and you set properties in the destination VC instance. In your case, create a public property NSString which holds the button text in your destination VC, and set it in your navigation section. This could be any class, or even a delegate, but a simple string should work.
Passing messages backwards (to previous VCs) can work the same way but it starts to get messy. You can programatically step back through the stack of VCs to find a particular (instance of) a VC. One of the answers to Get to UIViewController from UIView? gives sample code for stepping back through view controllers.
But if its simply forward communication, passing messages or information through
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
at the bottom of the VC code and the commented out lines below is very easy and safe.

Qt Designer undefined symbol with Custom Widget plugin

I am using Qt 4.7.2 under Fedora 14.
I have a working library of custom widgets which I am trying to integrate into Qt Designer.
There is a simple widget base class, then some more complex widgets inheriting from it.
The simple widget integrates fine, but I have a problem with the more complex ones.
The problem comes from the fact that that the more complex ones require a special structure to be passed to them on creation. So my code for creating a complex widget in the plugin is:
QWidget *myPlugin::createWidget(QWidget *parent)
{
my_struct *xyz = new my_struct;
return new myWidget("MyWidget",xyz, parent);
}
my_struct is just a simple C style struct with ints, doubles and arrays.
Then when I start Qt Designer with this plugin I get:
/usr/lib64/qt4/bin/designer: symbol lookup error: /usr/lib64/qt4/plugins/designer/libMyPlugin.so: undefined symbol: _ZN8MyWidgetC1E7QStringP17my_structP7QWidget
I am building a release version of the plugin, not a debug version.
I also tried defining xyz as a static class variable in the plugin and just passing its address to the constructor, but I still get the same error.
I also tried adding xyx as an unused static class variable to my simple widget and that does not give the error, so the error seems to be coming from the call to the myWidget constuctor.
Can anyone help me resolve this?
Thanks Arne,
You were right.
I added my library explicitly to the plugin's .pro file and then it worked.
What puzzles me is how could I build the plugin with no errors without the library?
And why did my simple widget work without the library?
The error message looks as if the linker did not find a definition for the constructor myWidget(QString, my_struct*, QWidget*). Have you added the relevant source file to your release build? Do you actually have a definition for this constructor? It is also possible that you have to exchange the object file linking order. I have seen this with larger projects in the past, so I wouldn't be too surprised. The object file containing the definition needs to be stated before the one using the definition.

Loading Nib and Displaying Window in Objective C++

I am trying to load a Nib from a C++ constructor with Objective C++. I have searched and found enough examples to get some code together but it doesn't display the window. Or any windows for that matter.
Here is an example of the contructor:
JokeSystem::JokeSystem() : fileSystem("/Library/Application Support/Jokes/")
{
try
{
randSystem = new RandSelect<std::string>
(fileSystem.getAllFileContents("%\n"));
}
catch (std::ifstream::failure)
{
NSWindowController * errorWindowControl = [[NSWindowController alloc]
initWithWindowNibName:#"ErrorWindow"];
[errorWindowControl showWindow: nil];
}
}
The purpose of the contructor is to load the contents of a directory into a string. What I am try to do is display the error window when the files fail to open.
ErrorWindow.nib has a single window with an OK button and a NSTextView for the error, I set up a NSWindowController in the nib and connected it to the window.
My only link has been that most examples show this [errorWindowControl showWindow: self];
rather than showWindow: nil but because this is a C++ constructor I it doesn't have self and this doesn't work.
If it matters this contructor is called from the awakeFromNib method of the MainMenu.nib's primary NSObject.
Thanks
A bit of an odd way to approach Cocoa. I would encourage you to step back, learn Objective-C and then write your application with an Objective-C based Cocoa UI layer on top of whatever backing store or model layer you have.
In any case, there isn't anything particularly wrong with that code (save for the odd design).
The first thing to check is the return value of -initWithWindowNibName:. Is errorWindowControl actually non-nil? If it is nil, then the NIB failed to load.
How are you writing the Cocoa application itself? Standard app bundle using Xcode, I hope?
Also, you shouldn't be hardcoding the path to /Library/Application Support/. Actually, your application shouldn't use that directory as the only storage location; many users won't have write access to that directory and won't be able to install your app without administrator access.