qlabel mailto link in Qt 4.8.6 - c++

I've followed instructions given on previous questions like this
so now if I put a link to a regular page it opens fine with the default browser. But if I want to open a mailto link from QT QLabel 4.8.6 the link does nothing.
What am I doing wrong?
here is the code:
UpgradeMessageDialog* umd = new UpgradeMessageDialog();
umd->ui->label->setOpenExternalLinks(true);
umd->ui->label->setTextInteractionFlags(Qt::TextBrowserInteraction);
umd->ui->label->setText("<a href='mailto:user#foo.com?subject=Test&body=Just a test'>My link</a>");
umd->exec();
umd->ui->label->connect(umd->ui->label,
SIGNAL(linkActivated(const QString&)), umd,
SLOT(linkOpen(const QString&)));
(this is defined as a public slot in the appropriate h file)
void UpgradeMessageDialog::linkOpen(const QString &link)
{
QDesktopServices::openUrl(QUrl(link));
}
Just to clarify: I have a default mail program set up in my computer, and when I type mailto:a#b.c in the browser that program opens fine.

First, there are two ways to handle link activation in QLabel. You should use one of them, but I see you are trying to use both.
This two ways are:
Call openExternalLinks(true), so that QLabel will automatically open links using QDesktopServices::openUrl() instead of emitting the linkActivated() signal.
Connect to the linkActivated() signal and then manually open link in the connected slot (by calling QDesktopServices::openUrl() for example).
Also you use the exec() function wrong. You should put the exec() call after the connect() call, because exec() is blocking so the signal connection will actually happened after the dialog is closed.
So your code should be like this:
umd->ui->label->setText("<a href='mailto:user#foo.com?subject=Test&body=Just a test'>My link</a>");
connect(umd->ui->label, SIGNAL(linkActivated(QString)), umd, SLOT(linkOpen(QString)));
umd->exec();
or like this:
umd->ui->label->setTextFormat(Qt::RichText);
umd->ui->label->setTextInteractionFlags(Qt::TextBrowserInteraction);
umd->ui->label->setOpenExternalLinks(true);
umd->ui->label->setText("<a href='mailto:user#foo.com?subject=Test&body=Just a test'>My link</a>");
And a little advise: put the label initialization code into the UpgradeMessageDialog constructor.
UpgradeMessageDialog::UpgradeMessageDialog(QDialog* parent) : QDialog(parent)
{
ui->label->setTextFormat(Qt::RichText);
ui->label->setTextInteractionFlags(Qt::TextBrowserInteraction);
ui->label->openExternalLinks(true);
ui->label->setText("<a href='mailto:user#foo.com?subject=Test&body=Just a test'>My link</a>");
}
And then you can use your dialog this way:
QScopedPointer<UpgradeMessageDialog> umd = new UpgradeMessageDialog;
umd->exec();

#include <QUrl>
#include <QDesktopServices>
myLabel = new QLabel(this);
myLabel->setTextFormat(Qt::RichText);
myLabel->setText("Email:href='mailto:serge#essetee.be'>serge#essetee.be</a>");
myLabel->setOpenExternalLinks(true);
Now you just have to click the link and the standard mail client will be launched.

Related

How to add hyperlinks in Qt without QLabel?

I have some labels and layouts nested inside a QWidget to build a part of a sidebar. Each QWidget is its own section and one component currently looks like this:
To my understanding, you can only set hyperlinks with QLabel, but I'm trying to get the whole area between the white lines clickable. This is including the icon and the whitespace. Is there any way to achieve this?
This got marked as a duplicate to the opposite of what I was asking, so I'd like to reiterate that I'm trying to implement a hyperlink without QLabel.
You can easily have a widget open a link on click:
class Link : public QWidget {
Q_OBJECT
public:
Link(QUrl url, QWidget p = nullptr) : QWidget(p), _url(url) {}
QUrl _url;
void mouseReleaseEvent(QMouseEvent *) { QDesktopServices::openUrl(_url); }
}
You can avoid any extra signals and connections, and have each link widget store its own link internally, the url can be set on construction and changed at any time. Not using signals and slots makes it easier to change the link too, without having to disconnect previous connections.
IMO going for a signals and slots solution is only justified when you want different arbitrary behavior. In this case you always want the same - to open a particular link, so you might as well hardcode that and go for an easier and more computationally efficient solution.
I would just manually catch the SIGNAL for clicked() and use desktop services to open the url in code.
bool QDesktopServices::openUrl ( const QUrl & url ) [static]
Opens the given url in the appropriate Web browser for the user's desktop environment, and returns true if successful; otherwise returns false.
http://doc.qt.io/qt-4.8/signalsandslots.html
Using this type of syntax, or in the designer, you can also connect a signal to a slot.
connect(widgetThatRepresentsURL, SIGNAL(clicked()),
handlerThatWillOpenTheURL, SLOT(clicked_on_url()));
For widgets that don't have a signal set up for clicked (or whatever event you are interested in), you can subclass the widget in question and reimplement...
void QWidget::mousePressEvent ( QMouseEvent * event ) [virtual protected]
Specifically for creating a signal, there is emit. I've used this in the past like the following
void Cell::focusInEvent(QFocusEvent *e)
{
emit focus(this, true);
QLineEdit::focusInEvent(e);
}
with the following in the header
signals:
void focus(Cell *, bool);

Link clicked signal QWebEngineView

We already have QWebView implementation and now we want to migrate to QWebEngineView.
Through QWebView we have registered below signal to receive notification for any link is clicked on webview or not and we are getting signal in QWebView.
connect(m_WebView, SIGNAL(linkClicked(const QUrl &)),SLOT(urlLinkClicked(const QUrl &)));
In "urlLinkClicked" slot, we are opening new tab and open that URL into new tab.
We are facing some issue with QWebEngineView. As there is no such signal "linkClicked" exist in QWebEngineView. So we have tried below options but still not able to find the solution.
In main class, we have created WebEngineView class instance and setting WebEnginePage. We are able to render the website in view class but when we click on any link then we are not getting any signal so we are not able to open that new website in new tab.
m_WebEngineView = new QWebEngineView(this);
m_WebEngineView->setPage(new QWebEnginePage());
We have also override "acceptNavigationRequest" method to get the link clicked event in mainWebEngineView but we are not able to get the link clicked event.
Any suggestion i can try ?
Thanks in Advance.
Override QWebEnginePage::acceptNavigationRequest in QWebEnginePage subclass:
bool MyWebPage::acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame)
{
if (type == QWebEnginePage::NavigationTypeLinkClicked)
{
qDebug() << url;
}
return true;
}
use this in inherited WebEngineView and in inherited webpage we can find hoverdUrl
QWebEngineView *WebEngineView::createWindow(QWebEnginePage::WebWindowType type)
{
if(type==QWebEnginePage::WebBrowserTab)
{
if(!hoverdUrl.isEmpty())
QDesktopServices::openUrl(QUrl(hoverdUrl));
qGlobalDbg("Open external Url requiested in chat, url : " + hoverdUrl, toKIBANA|toLOG);
}
//qDebug()<<"============== link Clicked "<<hoverdUrl;
return NULL;
}
I think you could use the signal "urlChanged".
See the header "Signals" on there official documentation page.
http://doc.qt.io/qt-5/qwebengineview.html
If this does not help I need to know what version of the Qt framework you are using.
Best Regards
/ Rasmus
Unfortunately urlChanged signal that QWebenginePage has emits only when url of current page is changed. Previous linkClicked signal was also emitted when url of current page was not changed. There is a way to handle this, but you would need to have access to page source code.
This functiionality is achieved through QWebChannel class. You would need to create webChannel object and a special callback class, which would handle call backs from webpage in a way you like. Then you would need to set this webChanell on a page you want to and do all the connections like this:
MyCallBackObject* callback= new MyCallBackClass();
mWebChannel = new QWebChannel(this);
mWebChannel->registerObject(QStringLiteral("MyCallBackObject"), callback);
mWebView->page()->setWebChannel(mWebChannel); // mWebView is QWebEngineView
connect(callback, SIGNAL(urlChanged(QUrl)),
this, SLOT(linkClickedSlot(QUrl))); // connect statement, urlChanged is defined in your callback class, linkClickedSlot is a slot where you process clicked signal
For more reference - please use official example from qt or the one from kdab or this video from Qt Developer Days conference

Close QFileDialog only when click "open"

Whenever I select a file in my QFileDialog the accepted signal is fired and the window closes. I want to keep the window open so I can select multiple files and then capture the signal fired when "open" is clicked.
QFileDialog* myDialog = new QFileDialog(this);
myDialog->setFileMode(QFileDialog::ExistingFiles);
myDialog->setVisible(true);
What signals should I be connecting here to achieve this effect?
The QFileDialog::ExistingFiles should guarantee that multiple files can be selected. Given that, you can connect to the signal:
void QFileDialog::filesSelected(const QStringList & selected)
Directly from the documentation:
When the selection changes for local operations and the dialog is accepted, this signal is emitted with the (possibly empty) list of selected files.
However, if you are only interested in collecting such files, you can totally avoid signal-slot and write (taken again from the documentation):
QStringList fileNames;
if (dialog.exec())
fileNames = dialog.selectedFiles();
Note that in this case dialog object has been created on the stack (which is the common approach for such objects).
Your code looks fine to me. I believe you are double clicking on the file inside the dialog instead of holding on the Ctrl and single clicking on all the files you need.
You can optionally use an event filter and ignore the double click event.
Once you click on Open, you can get a list of all the file paths in the QStringList given by QFileDialog::selectedFiles(). Also it's better to use a stack variable here and use exec method to launch it as pointed out by BaCaRoZzo.
QFileDialog myDialog(this);
myDialog.setFileMode(QFileDialog::ExistingFiles);
if(myDialog.exec())
{
qDebug() << myDialog.selectedFiles();
}
Whenever I select a file in my QFileDialog the accepted signal is fired and the window closes. I want to keep the window open so I can select multiple files
All other answers is just solution for selection many files one time and CLOSE window after Open button pressing. Get my solution, it is not very simple because it required lot of work:
I used lamda expressions and new signals and slots syntax in my answer, but you can use old syntax or add
CONFIG += c++11
to the .pro file and use lambdas.
Subclass QFileDialog:
Header:
#ifndef CUSTOMFILEDIALOG_H
#define CUSTOMFILEDIALOG_H
#include <QFileDialog>
#include <QDebug>
class CustomFileDialog : public QFileDialog
{
Q_OBJECT
public:
explicit CustomFileDialog(QWidget *parent = 0);
void setDefaultGeo(QRect);
signals:
void newPathAvailable(QStringList list);
public slots:
private:
bool openClicked;
QRect geo;
};
#endif // CUSTOMFILEDIALOG_H
When you click open, you hide your dialog, not close! Cpp:
#include "customfiledialog.h"
CustomFileDialog::CustomFileDialog(QWidget *parent) :
QFileDialog(parent)
{
openClicked = false;
connect(this,&QFileDialog::accepted,[=]() {
openClicked = true;
qDebug() << openClicked;
this->setGeometry(geo);
this->show();
emit newPathAvailable(this->selectedFiles());
});
}
void CustomFileDialog::setDefaultGeo(QRect rect)
{
geo = rect;
}
Usage:
CustomFileDialog *dialog = new CustomFileDialog;
QStringList fileNames;
dialog->setFileMode(QFileDialog::ExistingFiles);
dialog->show();
dialog->setDefaultGeo(dialog->geometry());
connect(dialog,&CustomFileDialog::newPathAvailable,[=](QStringList path) {
qDebug() << path;
});
Why do you need setDefaultGeo? Without this method, your window will move after Open pressing.
What we get?
I open filedialog and select two files:
I clicked Open, but window didn't close! You can choose new files again and again!
One more file and so on:
Window will closed only when user press Close button, but you will have all path which user choose.
As you said:
I want to keep the window open so I can select multiple files
You get this.
I don't think anyone has understood the question (or it could be just me looking for my own solution)...
I had the same issue. As soon as I clicked a file the dialog would close. I couldn't ever select a file and then click "Open" because the dialog instantly closed as soon as I single clicked a file.
related: qtcentre.org/threads/48782-QFileDialog-single-click-only
It turns out it was my linux os settings (under mouse). File opening was set to single-click. I still feel like something external might have toggled this but that is just speculation. It appears Qt was going the right thing. Check another application, like kate on KDE and see if it has the same behavior. That is what clued me in to the source of my issue.

Display QProcess output in another window

I'm using the QT Creator on Ubuntu.
I have GUI with a mainwindow and another window called "progress".
Upon clicking a button the QProcess starts and executes an rsync command which copies a folder into a specific directory. I created a textbrowser which reads the output from the rsync command. Also clicking the button causes the "progress" window to pop up.
So far so so good, now my problem.
Instead of showing the rsync output in my mainwindow i want it to be in progress.
I've tried several methods to get the QProcess into the progress via connect but that doesn't seem to work.
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
if (ui->checkBox->isChecked()
)
m_time ="-t";
QObject parent;
m_myProcess = new QProcess();
connect(m_myProcess, SIGNAL(readyReadStandardOutput()),this, SLOT(printOutput()));
QString program = "/usr/bin/rsync";
arguments << "-r" << m_time << "-v" <<"--progress" <<"-s"
<< m_dir
<< m_dir2;
m_myProcess->start(program, arguments);
}
progress.cpp
void Progress::printOutput()
{
ui->textBrowser->setPlainText(m_myProcess->readAllStandardOutput());
}
I know it's pretty messy iv'e tried alot of things and haven't cleaned the code yet also I'm pretty new to c++.
My goal was to send the QProcess (m_myProcess) to progress via connect but that didn't seem to work.
Can you send commands like readyReadAllStandardOutput via connect to other windows (I don't know the right term )?
Am I doing a mistake or is there just another way to get the output to my progress window ?
m_myProcess is a member of the class MainWindow and you haven't made it visible to the class Progress. That's why you have the compilation error
m_myProcess was not declared in this scope
What you could do:
Redirect standard error of m_myProcess to standard output, such that you also print what is sent to standard error (unless you want to do something else with it). Using
m_myProcess.setProcessChannelMode(QProcess::MergedChannels);
Make the process object available outside MainWindow
QProcess* MainWindow::getProcess()
{
return m_myProcess;
}
Read the process output line by line in Progress. It needs to be saved in a buffer because readAllStandardOutput() only return the data which has been written since the last read.
... // somewhere
connect(window->getProcess(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput())
...
void Progress::printOutput(){
//bigbuffer is member
bigbuffer.append(myProcess->readAllStandardOutput();)
ui->textBrowser->setPlainText(bigbuffer);
}

Making QLabel behave like a hyperlink

how can I make a QLabel to behave like a link? What I mean is that I'd like to be able to click on it and then this would invoke some command on it.
QLabel does this already.
Sample code:
myLabel->setText("Click Here!");
myLabel->setTextFormat(Qt::RichText);
myLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
myLabel->setOpenExternalLinks(true);
The answer from cmannnett85 is fine if you just want to open a URL when the link is clicked, and you are OK with embedding that URL in the text field of the label. If you want to do something slightly custom, do this:
QLabel * myLabel = new QLabel();
myLabel->setName("myLabel");
myLabel->setText("text");
myLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
Then you can connect the linkActivated signal of the label to a slot, and do whatever you want in that slot. (This answer assumes you have basic familiarity with Qt's signals and slots.)
The slot might look something like this:
void MainWindow::on_myLabel_linkActivated(const QString & link)
{
QDesktopServices::openUrl(QUrl("http://www.example.com/"));
}