How can I check if QPdfWriter object can write to the specified file? - qt

I am creating the PDF documents in Qt using command:
QPdfWriter *pdf;
pdf = new QPdfWriter(filename);
Sometimes the object is not created due to a wrong filename or document exists and is open in other application...
How can I check if object was created (if the pdf pointer points to the valid object)?
EDIT: My mistake was, that object is not created. It is not true. The QPdfWriter object is created, but there is no exception or error generated.
I can set some properties.
The problem will occur later when I am trying to write something to the document - see comments of the last 3 commands:
pdf->setParent(this);
pdf->setPageSize(QPdfWriter::A4);
pdf->setPageOrientation(QPageLayout::Orientation::Landscape);
QPainter *p = new QPainter(pdf); //got message: QPainter::begin(): Returned false
ui->chartView->render(p); // no error
p->end(); // got message: QPainter::end: Painter not active, aborted
I read the documentation of QpdfWriter and parent classes QPagedPaintDevice and QPaintDevice. I cannot find any property/method to check if I can write to the document...
So question - how to check if I can write to the document?

Ive just stumpled over the same issue, the hint with bool QFileInfo::isWritable() const didn't do the trick for me. Though you basically gave the answer yourself with the comment on the third last command, with the return value of QPainter::begin() you can check if the QPdfWriter can generate the pdf.
QPainter *p = new QPainter;
if (p->begin(pdf)) {
ui->chartView->render(p);
p->end();
} else {
// error message...
}

Related

Why am I getting an object reference error?

I'm a beginner developer and I'm trying to make a 2D survival type game where you have to break a trees. I'm using a raycast to detect when you click a tree. When I run the program, it says "Object reference not set to an instance of an object". Usually you just have to declare a public variable, but all variables are set. Never seen this before. Here's what I have:
if (Input.GetMouseButtonDown(0))
{
Debug.DrawRay(transform.position, mousePosition * 0.1f, Color.red);
RaycastHit2D hit = Physics2D.Raycast(playerRb.transform.position, mousePosition, 0.1f);
if (hit.collider != null)
{
hit.transform.GetComponent<TreeScript>().treeHealth -= 1;
}
}
I've pinpointed the problem to be on the last line. I have a script called TreeScript and a variable there for the treeHealth.
I found what my problem was. I used "if (hit.collider != null)" and then attempted to modify a specific component. I believe the raycast was hitting other objects and failing to transform it because it didn't have the treeScript component. I just added an if statement to detect if the object I hit is a tree.

`double free or corruption (out)` error on a stack QDialog with the `WA_DeleteOnClose` attribute set

Given the following fragments of code :
class MyDialog : public QDialog
{
...
};
MyDialog::~MyDialog()
{
qInfo() << "~MyDialog()";
}
and
// scope begins
MyDialog d;
d.setAttribute( WA_DeleteOnClose, true );
int result = d.exec();
qInfo() << "After exec";
// scope ends
I get the following output
~MyDialog()
double free or corruption (out)
Aborted (core dumped)
Without d.setAttribute( WA_DeleteOnClose, true ); everything is fine and expected.
NOTE : I know that there is no need to use the delete on close in this case as the dialog deletes when leaving the scope. I also don't need for a "better solution" etc (I've read a lot of posts on SO and Qt Centre Forum with these irrelevant answers). The question is Why the error occurs at the first time the ~QDialog() is called ? And maybe Am I right that the error occurs at the first time the ~QDialog() is called?
I've got the answer in the Qt Forum : link.
The source code for the QDialog class contains the following lines:
//QDialog::exec()
if (deleteOnClose)
delete this;
return res;
which is, ofc, causes a crash if this points to a stack object.
Try this instead:
MyDialog* d = new MyDialog;
d->setAttribute( WA_DeleteOnClose, true );
int result = d->exec();
Either new QobjectDerived or new QobjectDerived(this) for dynamic allocation and then the dynamic deallocation could finalize the object destruction just once. That attribute WA_DeleteOnClose set is obviously provoking internal delete when the dialog getting closed but no second destructor call as in case with that object allocated on stack.
You're creating an object on the stack and then try to delete it with delete (indirectly via the WA_DeleteOnClose - flag). I don't see why you would not get a double delete then.

Use QTest macros (QVERIFY, QCOMPARE, etc.) in function other than the test function

In general, the macros QVERIFY, QCOMPARE, etc. shall not be used outside a test function. The reason is, that in case of a failure, they interrupt the test with a return.
If I want to do tests in a function, I should do them by hand and return false if one of them fails. Then call the function with QVERIFY. But when I do this, I miss out the detailed output of the macros like the line where the error occurred.
So I'm looking for a way to use the macros outside of a test function. One solution is to create my own macro that interrupts the test when a macro call in the underlying function fails. The main problem here is to detect when a test has failed. Looking into Qt's code, in case of a fail the variable QTest::failed is set to true. But I don't have access to this variable.
Is there a way to find out if a QtTest macro has failed?
Yeah, Qt does not really offer anything here because the test will not really get interrupted within your own function. The control flow cannot be as easily disturbed. You would need to throw an exception and make sure it's correctly caught.
What I'm doing now is just returning a const char* (works when using a string literal). If the function actually returns something, std::variant can be used, e.g.:
std::variant<MyObject, const char*> createObject() {
// do some preparations
if(preparationsFail) {
return "Error occurred";
// all worked
// ...: create some myObject
return myObject;
}
void MyTest::testFunction() {
auto result = createObject();
if(const char** error = std::get_if<const char*>(&result)) {
QVERIFY2(false, *error); // we get pointer to value, so type is **
}
// else, work with myObject by std::get<MyObject>(result);
}
Not as concise as would be desired, but it works.
It can be made more beautiful by wrapping const char* and, depending on your style, by using std::visit etc. but that's up to you and your style.

Unable to evaluate the expression Cannot find source class for java.util.List

I response this error when get JSON data by retrofit.
List<NewLicense> result = null;
Call<List<NewLicense>> serviceResult = ShahrdariApp.getShahrdariWebService().getLicenses(Configuration.getInstance().getString(SharedPrefs.MAC_ADDRESS), id);
try {
Response<List<NewLicense>> response = serviceResult.execute();
result = response.body();
Log.d("responseCode", String.valueOf(response.code()) );
} catch (Exception e) {
exceptionHandling(e);
Log.d("responseCode", String.valueOf(e.getMessage()) );
}
return result;
I had the same issue and forgot to set the Project SDK added this and it resolved the issue.
Simply restarting the IDE via File -> Invalidate caches can often solve this issue.
I faced the message
Unable to evaluate the expression Cannot find source class for
java.util.List
in hovering a List field while debugging in IntelliJ IDEA 2022.1.3 (UltimateEdition).
Even though an SDK was assigned to my Project, it helped to visit
IDEA ->File ->Project Structure -> Platform Settings ->SDKs and re-assign the SDK already visible in the list.
Namely I assigned openjdk-1.8.0.302-1, applied "OK", after that it was possible to debug a List foo.
IDE restart after that may additionally be necessary.

Spark memory leaks

I've been trying to track down memory leaks in our application, and keep finding myself back looking at Spark components as the culprit.
I think I've found the cause, but my understanding of Garbage Collection / mark & sweep is not too hot, so I'd like to verify my findings.
Many classes in Spark use RichEditableText for displaying their text properties (ComboBox,TextInput).
RichEditableText has a local textContainerManager property, and frequently calls compose() on this.
Here's the relevant abridged extract from TextContainerManager
// Line 282 - 292:
static private var stringFactoryDictionary:Dictionary = new Dictionary(true);
static private function inputManagerStringFactory(config:IConfiguration):StringTextLineFactory
{
var factory:StringTextLineFactory = stringFactoryDictionary[config];
if (factory == null)
{
factory = new StringTextLineFactory(config);
stringFactoryDictionary[config] = factory;
}
return factory;
}
// Line 1204:
public function compose() {
// Line 1238:
var inputManagerFactory:TextLineFactoryBase = (_sourceState == SOURCE_STRING) ? inputManagerStringFactory(_config) : _inputManagerTextFlowFactory;
// Line 1242:
inputManagerFactory.swfContext = Configuration.playerEnablesArgoFeatures ? this : _swfContext;
}
Line 1242 is the crucial line here, as it gives the static dictionary a reference to our component.
(Note - I've checked this with the debugger to confirm which branch of the ternary gets executed.) This would prevent the instance from ever being garbage collected.
Eg: Static dictionary has a value with a reference to the instance -- instance cannot be GC'd.
In turn, this would prevent any other instances which have a reference to the instance of TextContainerManager from being GC'd also.
While this theory certainly matches what I'm seeing in our app, I can't beleive that there really is a memory leak in such a low-level spark component.
Could someone please shed some light on this?
BTW - I've opened a defect on bugs.adobe.com to track this issue, should it prove to be a genuine bug:
https://bugs.adobe.com/jira/browse/SDK-29531
I've heard there are several memory problems related to TLF.
That should be corrected in the Flex 4.5 SDK.
In the meantime, you could still open a ticket on http://bugs.adobe.com/jira/

Resources