QT- Signal and Slot setEnabled(bool) slot not working - c++

I have been working on a simple notepad application using QT, and am currently stuck at a place where I have to disable the actionUndo and actionRedo when undo or redo are not applicable respectively. I used the connect method of QT, and currently my constructor function (along with includes) looks like this:
#include "notepad.h"
#include "ui_notepad.h"
#include "about.h"
#include <QFile>
#include <QTextStream>
#include <QFileDialog>
#include <QIcon>
#include <QFont>
#include <QFontDialog>
#include <QTextCursor>
Notepad::Notepad(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Notepad)
{
ui->setupUi(this);
setWindowTitle("QNotepad");
setWindowIcon(QIcon(":/icons/icons/qnotepad.png"));
setCentralWidget(ui->textBody);
//Enabling the options, only when applicable
connect(ui->textBody, SIGNAL(undoAvailable(bool)), ui->actionUndo, SLOT(setEnabled(bool)));
connect(ui->textBody, SIGNAL(redoAvailable(bool)), ui->actionRedo, SLOT(setEnabled(bool)));
}
Full sources are here
But seems it is not working as when I run the program, the actionUndo and actionRedo remains enabled even when there is no undo and redo operations available.
I am using Arch Linux as the primary development environment

Qt Ui elements (widgets, actions, etc.) are enabled by default, so you need to uncheck the enabled flag for the Undo and Redo action in the property window of Qt designer for your notepad.ui file.
Alternatively you could do it in the constructor of your window like this:
ui->actionUndo->setEnabled(false);
ui->actionRedo->setEnabled(false);
//Enabling the options, only when applicable
connect(ui->textBody, &QTextEdit::undoAvailable, ui->actionUndo, &QAction::setEnabled);
connect(ui->textBody, &QTextEdit::undoAvailable, ui->actionRedo, &QAction::setEnabled);
In this way they will be on/off only when the QTextEdit emits the signal.
Also consider to use the functor syntax for your signal/slot connection, as shown in my code snipped, because it has several advantages. See here to learn more.

Related

Modbusclient as a console application, "Stuck in Connectingstate loop"

I'm trying hardly to convert the Modbusmaster example (qt example) which is a widget application to a console application. I wanted to build a connection between a local slave and my master. The problem I'm facing is that my code is changing its state to “Connecting state” ,gets stuck and doesn't want to build a connection. That's why, I recon that the Modbus library is limited and it's only compatible with the widget form.
Could someone tell me if my guesses are right.
down below you will find my code:
#include <QCoreApplication>
#include <QDebug>
#include <QModbusDataUnit>
#include<iostream>
#include <QTimer>// this bib was add to the 50ms Loop check
#include <string>
#include <QString>
#include <QThread>
#include <QModbusTcpClient>
#include <QModbusDataUnit>
#include <QUrl>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Mainmodbus T ;
T.modbusDevice = new QModbusTcpClient();
if (!T.modbusDevice) qDebug()<<"error 1";
if (T.modbusDevice->state() != QModbusDevice::ConnectedState) {
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
T.modbusDevice->connectDevice();
while(true){
qDebug()<<T.modbusDevice->state();}
}
return a.exec();
}
I can be wrong but I think the QModbusDevice::ConnectingState you see actually means your server is up and running and waiting for a connection.
I guess what you are missing is opening a connection from a Modbus client. You can do that with different tools, I guess running the client example
would be a good idea. Otherwise, you can use QModMaster or any other tool you like.
Once you open the connection from the client the state on your server should change to QModbusDevice::ConnectedState.
Be aware that the server you built is just an empty shell, there is no register map defined so if you query the contents of any register from the client you will get an error.
At the very minimum, you should at least define a map with some default values or get them from command-line options. To do that you need to look at the server example a bit more carefully.
First you need to define the register map with something like this:
QModbusDataUnitMap reg;
reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 });
reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 });
reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 });
reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 });
modbusDevice->setMap(reg);
setupDeviceData();
And then for the setupDeviceData(); you can copy the function in the example but instead of taking the data from the widget, you will have to load default values or something from the command line.
In answer to your question: no, there should be no limitation and you should be able to run the server from the command line. I wonder why somebody on his/her right mind would want to do that when you have excellent alternatives like libmodbus. But honestly, I won't miss much sleep wondering.

How to block a Url using c++ qt application

I want to create a QT application with webkit browser with below feature:
By default, google website (http://google.com) is displayed to user and it must allow access to all the url except google hangout.
I created below program which will open the google url but don't know how to block the desired url:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWebkitWidgets/QWebView>
#include <QUrl>
MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setup(this);
ui.webView->load(QUrl("http://google.com"));
}
MainWindow::~MainWindow()
{
delete ui;
}
I´m going to make this a brief answer. Qt provides a number of great examples with the installation, you should look at the Tutorial examples for the Webview one, it´s a QML application -- and it is really easy to modify it to your needs.
As the navigation bar is a separate element, which is separately scripted, you can make it callback to C++ where you can apply a filter to it. The example you should look for is called ´quicknanobrowser´.
Edit
To clarify, based on a comment, you can also act on the signal when a new page is loaded. This would be placed inside BrowserWindow.qml, ctrl+f for "onNewViewRequest", which is another signal that is acted upon in the same manner:
onLoadingChanged: {
if(loadRequest.url == "www.blockedurl.com")
{
// Do what you want here
}
}

Show QWidget or QWindow near QSystemTrayIcon in QT C++

I have managed to get the QSystemTrayIcon visible similar to this:
using the following line of code (with the signal slots working):
#include "dialog.h"
#include "ui_dialog.h"
#include <QMessageBox>
#include <form.h>
Dialog::Dialog(QWidget *parent)
: QDialog(parent), ui(new Ui::Dialog)
{
ui->setupUi(this);
QIcon icon("/Users/JohnnyAppleseed/IMAGE.png");
m_ptrTrayIcon = new QSystemTrayIcon(icon );
m_ptrTrayIcon->setToolTip( tr( "Bubble Message" ) );
// m_ptrTrayIcon->setContextMenu(m_trayIconMenu);
connect(m_ptrTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
}
Dialog::~Dialog()
{
delete ui;
}
However, when I try to implement code to show the QWidget/QWindow near the QSystemTrayIcon that I have created, it fails to show up near it. It also shows up and disappears quickly as well (even if I didn't want it near the QSystemTrayIcon) using this code:
void Dialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
form fr;
fr.setWindowFlags(Qt::Popup);
fr.show();
}
For the sake of being clear, I would like to show my QWidget/QWindow just like VMWare Fusion's approach (or the clock that is found on Microsoft Windows Vista or later...)
Mac OS X / Linux
Microsoft Windows
Can some one please point out what am I doing wrong? Thanks!
To make things much simpler, download the project: http://zipshare.net/sv
UPDATE #1
Regarding the QWidget/QWindow flicking issue, vahancho advised me to move the form fr; from the void Dialog::iconActivated(QSystemTrayIcon::ActivationReason reason) function to the header of the working window. And it worked successfully all thanks to vahancho. The window now shows up, but its not near the QSystemTrayIcon yet :(
The problem is that you create you form object in the stack and it gets deleted as soon as the execution goes out of you iconActivated() slot. That is why it disappears as soon as you see it. To solve the problem you need to create your pop up in the heap.
UPDATE
In order to place you dialog near the tray icon you have to determine the tray icon position. To do that you can use QSystemTrayIcon::geometry() function. You code will look like (adjust the coordinates according to your needs):
QRect rect = m_ptrTrayIcon->geometry();
fr.move(rect.x(), rect.y());
fr.show();

QGLWidget crashes when added to layout

I am trying to adapt the opengl Es example "Hello GL" featured here - http://qt-project.org/doc/qt-4.8/opengl-hellogl-es.html. I am basically looking for a simple way to get a 3D graphics rendering window into a form made in Qt creator.
The first thing I tried:
Grid layout is a layout I created in Qt Creator.
#include <QProcess>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTimer>
#include "glwidget.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
GLWidget *glwidget = new GLWidget(); // This is mandatory. No problems here.
QTimer *timer = new QTimer(this); // Need this for the example to work.
timer->setInterval(10); // Also necessary.
ui->gridLayout->addWidget(glwidget);
Which compiles, but then promptly crashes with a segmentation fault.
ui->gridLayout->addWidget(new GLWidget);
Segfaults the same way.
The debugger points me toward line 104 of qgridlayout.h:
inline void addWidget(QWidget *w) { QLayout::addWidget(w); }
Not sure what to make of that. Perhaps the QGLWidget wants to do something before I call ui->setupUi(this)? Perhaps it can't add the widget to the layout for some reason?
Of course if I comment out the line where I am added the widget, the program works flawlessly.
Any ideas for what's going on here?
Edit: I have fixed this. It was problem with order of operations - I called updateui too quickly.
The setupUi function in the generated form class initializes all variables of the form class, so using the variables before the form is initialized is undefined behaviour, since the variables contain garbage.
So the solution is to call:
ui->setupUi(this)
Before any call that uses variables in the ui object.
I'm not sure, but I think the problem is with the following line:
ui->gridLayout->addWidget(GLWidget);
I think, you should write it as follows:
ui->gridLayout->addWidget(glwidget);
// declare glwidget as member of your class
GLWidget *glwidget;
//in constructor use
glwidget = new GLWidget();

Create QAction with shortcut, without inserting in menu

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <cassert>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QAction* back = new QAction(this);
back->setVisible(true);
back->setShortcut(QKeySequence("Ctrl+M"));
bool cres = connect(back, SIGNAL(triggered(bool)), this, SLOT(mySlot()));
assert(cres);
}
In this code I tried to catch Ctrl+M key event. I don't want to put the action in menu. connect returns true but mySlot is never called. When action is inserted in menu, shortcut works well. What I have done wrong?
QAction is dormant until you insert it somewhere. As vahancho has suggested, use QShortcut. You need to instantiate the shortcut for each top-level widget (window) where you want it to be active. Thus if you have 5 top-level windows, you'll need 5 shortcuts, each having one of windows as its parent.
There is no way to use QShortcut as a global shortcut without the gui. QShortcut is only active when its associated widget has focus. The widget could be a top-level window.
System-global shortcuts are the subject of this question.