QClipboard cannot get clipboard data if copied from Notepad/Chrome - c++

In my program, my users can copy a string of text from anywhere and paste it into my program. I use the simple QApplication::clipboard()->text(); function and everything works as expected. However, several of my users are having problems when trying to copy and paste on Windows 8.1
Here is how I access the clipboard text from my paste function:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(QApplication::clipboard()->text().isEmpty())
return;
//do something with clipboard
But if the text was copied from Notepad or Chrome, the text is ALWAYS empty. Windows 7 users have not had any problems. Not ALL Windows 8 users have this issue, it's only a handful but the issue it consistent. When copied from some other random places or within my program itself, the clipboard works fine.
I've tried using mimeData. When using the function formats(), only plain text is an available format, but the text is always empty.
The text being copied from Notepad/Chrome shows up fine in clipboard viewers and stuff and can be pasted elsewhere in other programs.
Copying and pasting is a very important feature in my program and its frustrating that my users can't copy and paste from Notepad or Chrome.
Any ideas? Thanks for your time. :)
EDIT: I tried using the "windows" style technique. There was no change. Here is my current, still unworking code:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(clipboard.isEmpty())
{
//might not actually be empty. Check using the other technique
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL))
{
HGLOBAL hGlobal = GetClipboardData(CF_TEXT) ;//hGlobal is NULL
if (hGlobal != NULL)//This never gets called because it is NULL
{
LPTSTR lpszData = (LPTSTR) GlobalLock(hGlobal) ;
if (lpszData != NULL)
{
clipboard.fromLocal8Bit((const char *)lpszData);
GlobalUnlock(hGlobal) ;
}
}
CloseClipboard() ;
}
if(clipboard.isEmpty())
return;
}
The copied text shows up fine in a clipboard viewer, but my program can't get to it no matter what:
How come GetClipboardData() isn't picking anything up? Again, the copied text CAN be pasted in any other program I've tried... just not mine. But if copied from somewhere else, it works no problem.

EDIT: With this version, When the user copies text and text gets to clipboard, a function copies the text this time to an internal text file not directly to your program, using QFile. Another function copies the text from the internal text file to your program. By this way, i think your program wouldn't have to directly deal with text in the clipboard
clipboard.h
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#include <QDialog>
#include <QClipboard>
#include <QLabel>
#include <QHBoxLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QFile>
#include <QTextStream>
class ClipBoard : public QDialog {
Q_OBJECT
public:
explicit ClipBoard(QWidget *parent = 0);
~ClipBoard();
private slots:
//the functions that will copy and paste text from the text file
void copyToTextFile();
void paste();
private:
QPushButton *button;
QTextEdit *edit;
QString textFromClipBoard;
QClipboard *clipBoardText;
QString clipboard;
};
#endif // CLIPBOARD_H
clipboard.cpp
#include "clipboard.h"
#include "ui_clipboard.h"
ClipBoard::ClipBoard(QWidget *parent) : QDialog(parent) {
button = new QPushButton("&Paste Copied Text");
edit = new QTextEdit;
/*when user copies text and text gets to clipboard, the text is copied
from clipboard to a text file then copied from the text file to the
program*/
connect(button, SIGNAL(clicked()), this, SLOT(copyToNotepad()));
connect(button, SIGNAL(clicked()), this, SLOT(paste()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button);
layout->addWidget(edit);
setLayout(layout);
}
/*This function copies text from the clipboard to an internal text file
created by the program*/
void ClipBoard::copyToTextFile() {
clipboard = QApplication::clipboard()->text();
QFile output("out.txt");
if (output.open(QIODevice::ReadWrite | QFile::Truncate |
QIODevice::Text)) {
QTextStream out(&output);
out << clipboard;
}
}
/*This function then copies the text from the internal text file and pastes
it to the text edit. So the program doesn't have to deal directly with the
clipboard*/
void ClipBoard::paste() {
QFile input("out.txt");
if (input.exists()) {
if (input.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&input);
clipboard = in.readAll();
}
}
edit->setText(clipboard);
}
ClipBoard::~ClipBoard() {
}
main.cpp
#include "clipboard.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
ClipBoard w;
w.show();
return a.exec();
}
Look through and compare with your part of the code to see if there's something you did wrong. But as to how you claim it works on some Windows 8.1 systems and don't on others baffles me.

I had similar issue,
the solution for me is sleep.
void MainWindow::on_clipboard_change(){
QThread::msleep(1); //without this line I get allways empty clipboard
QString text = QGuiApplication::clipboard()->text();
qDebug() << "clipboard change event triggered ( " << text << " )";
}

Related

Why QFileDialog::selectFile doesn't work?

I am using Qt 5.12 and trying to write test (using QTest) for opening of project stored in some xml format.
In test I use QTimer::singleShot to wait QFileDialog to appear as proposed in QT close window by QTest in locked thread.
The problem is that QFileDialog::selectFile doesn't select anything. This means that OK button is not active, so I can't click on it in my test.
I assume in the following example that full path to file is /tmp/project.xml. Notice that QFileDialog::setDirectory works great: when the following example starts, you are in /tmp dir instead of /.
#include <QApplication>
#include <QFileDialog>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTimer::singleShot(300, []() {
QWidget* window = nullptr;
while (!window) {
window = qApp->activeModalWidget();
}
QFileDialog* fd = qobject_cast<QFileDialog*>(window);
fd->setDirectory("/tmp");
fd->selectFile("project.xml");
});
QString path = QFileDialog::getOpenFileName(nullptr, "Open Project",
"/", QString(),
nullptr, QFileDialog::DontUseNativeDialog);
}
The function selectFile didn't work because of the file name text box (lineEdit) is focused. This behavior comes from the implementation of QFileDialog::selectFile() :
void QFileDialog::selectFile(const QString &filename)
{
// ... function body
//Put the filename into the lineEdit when :
//1. The dialog is not visible or
//2. The lineEdit is not focused.
if (!isVisible() || !d->lineEdit()->hasFocus())
d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
}
To make the program works, there are two ways :
Put the file name directly in the text box
Give the focus away then call selectFile
fd->setDirectory("/tmp");
QLineEdit * lineEdit = qobject_cast<QLineEdit*>(fd->focusWidget());
if( lineEdit ){
//Method 1
lineEdit->setText("project.xml");
//Method 2
lineEdit->nextInFocusChain()->setFocus();
fd->selectFile("project.xml");
}else { //no lineEdit focus found
fd->selectFile("project.xml");
}

c++ gui button output

i have a few questions regarding the gui of cplusplus using Qt creator
well i output an array using a forloop when user's choice is for example "1"
so in qt i created a button for that and i linked it with another window
so when i press on the button it opens another window
now i want to add the output of the forloop into this window
should i include iostream in the new window's .cpp file?
or what should i enter exactly?
in the mainwindow.cpp file here is the code i used to open a new window
void MainWindow::on_pushButton_clicked()
{
movies movies;
movies.setModal(true);
movies.exec();
}
thanks.
You should add a QTextEdit to your window (can be done via Qdesigner). And give this object a name e.g. Textout. Then in the code you should get a pointer to this object through your ui object. And you can use one of many methods to set the text of this object. setText is one option
ui->Textout->setText(Your_output_as_qstring)
Your can use QTextStream to format your text if necessary. Formating can be done with QString as well.
example:
#include <sstream>
#include <QLabel>
#include <QApplication>
int main(int argc, char *argv[])
{
std::stringstream ss;
for (auto s: {"first line", "second line"})
ss << s << std::endl;
QApplication a(argc, argv);
QLabel l;
l.setText(ss.str().c_str());
l.show();
return a.exec();
}

Issue with deleting text in file

Explaining of my purpose:
my program have two section first reading two word from user(second word is meaning of first one) and save this words in two text file second section is showing or deleting words as desire of user.
What is my issue?:
my program works perfectly but after days will something like this happen:
when i try to delete two words from .txt files(i mean 1 word with meaning of it) first word will delete but second word(meaning) will not delete, it sounds like .txt file corrupted only thing that will fix every thing is delete that text file and create new one and thats very annoying that means lose all informations
note: first word and second word are in separate files. second words are still able to show.
what did i try?:
i try to check that is second word text file open or closed. that sounds like it will open or close in right time.
check that if text file is read-only. that wasnt.
i dont know what really happening here :( !!!!
here its my delete code am i missing something ?
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <fstream>
#include <QFile>
#include <QTextStream>
#include <QIODevice>
#include <QDebug>
#include <QMessageBox>
#include <QProcess>
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
void newFunc();
void restartApp();
void makeFa();
int xy=-1;
ifstream sfile("en.txt");
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
newFunc();
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void newFunc(){
QFile check("EnTemp.txt");
if(check.exists()){
}
else{
ofstream EnTemp("EnTemp.txt");
}
}
void restartApp()
{
qApp->quit();
QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
}
void MainWindow::on_Enter_clicked()
{
if((ui->InEN->text().isEmpty()) || (ui->InFa->text().isEmpty())){
QMessageBox msg;
msg.setText("Fields are empty");
msg.exec();
}
else{
QString en,fa;
en=ui->InEN->text();
fa=ui->InFa->text();
// saving EN words
QFile dataE("en.txt");
dataE.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream streamE(&dataE);
streamE<<en<<"\r\n";
dataE.close();
// saving FA words
QFile DataF("fa.txt");
DataF.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream streamF(&DataF);
streamF.setCodec("UTF-8");
streamF<<fa<<"\r\n";
DataF.close();
ui->InEN->clear();
ui->InFa->clear();
}
}
void MainWindow::on_Next_clicked()
{
QFile EnTemp("EnTemp.txt");
EnTemp.open(QIODevice::WriteOnly);
QTextStream GetTemp(&EnTemp);
if(!sfile.eof()){
string get;
getline(sfile,get);
ui->ShowEn->setText(QString::fromStdString(get));
ui->ShowFa->clear();
xy++;
GetTemp<<xy;
EnTemp.close();
}
else{
restartApp();
}
}
void MainWindow::on_mean_clicked()
{
cout<<xy;
QFile openFa("fa.txt");
QString getFa;
openFa.open(QIODevice::ReadWrite);
QTextStream pointfa(&openFa);
pointfa.setCodec("UTF-8");
int forword=0;
while(forword<=xy){
getFa=pointfa.readLine();
forword++;
}
ui->ShowFa->setText(getFa);
openFa.close();
}
void MainWindow::on_delete_2_clicked()
{
makeFa();
ofstream tempE;
if(!ui->ShowEn->text().isEmpty() | !ui->ShowFa->text().isEmpty())
{
QMessageBox msg;
int ret;
msg.setText("Are you sure you want to delete this words?");
msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msg.setIcon(QMessageBox::Warning);
ret= msg.exec();
switch(ret){
case QMessageBox::Yes:
QString input;
input=ui->ShowEn->text();
string line;
ifstream DataE;
DataE.open("en.txt");
tempE.open("tempE.txt");
while(getline(DataE,line)){
if(line != input.toStdString()){
tempE<<line<<"\r\n";
}
}
QString inputF;
inputF= ui->ShowFa->text();
string lineF;
ifstream DataF;
ofstream tempF("tempF.txt");
DataF.open("fa.txt");
while(getline(DataF, lineF)){
if( lineF != inputF.toStdString()){
tempF<<lineF<<"\r\n";
}
}
DataE.close();
DataF.close();
tempE.close();
tempF.close();
sfile.close();
remove("en.txt");
remove("fa.txt");
rename("tempE.txt", "en.txt");
rename("tempF.txt", "fa.txt");
break;
}
}
else{
QMessageBox mass;
mass.setText("Fields are empty");
mass.exec();
}
restartApp();
}
void MainWindow::on_Restore_clicked()
{
xy= 0;
int reach=0;
string get;
QString s;
ifstream openTemp("EnTemp.txt");
openTemp>>xy;
while(reach<=xy){
getline(sfile,get);
reach++;
}
ui->ShowEn->setText(QString::fromStdString(get));
}
void makeFa(){
QFile tempF;
tempF.setFileName("tempF.txt");
tempF.open(QIODevice::ReadWrite | QIODevice::Append);
QTextStream stream(&tempF);
stream.setCodec("UTF-8");
tempF.close();
}
I'm on windows 8.1
i notice something new right now when i try to delete all information in second .txt file the size of file will be 3 bytes instead of 0 bytes
3 bytes for an otherwise empty file might match the UTF-8 BOM (not saying it is without knowing said bytes, but it is a strong hint). Your delete function might be fine (althought you should make the file filtering another function for clarity, and DRY), but would work only with ascii charset since you're relying on std::i/ofstream and std::string.
It might be (again, no certitude, just a wild guess) that you're creating a file with QFile, and that you put a "meaning" containing non-ascii characters and thus QFile automatically converts the file to an UTF-8 prefixed with BOM.
Would you mind updating your post with the file creation/update methods if you're uncertain of this lead?
[Edit] The other option would be that you're writing non ascii characters with ofstream which would probably lead to the "meaning" not being found, and thus the file being fully replicated.

Qt QFileDialog pops up once more

I am developing a system and for the GUI I preferred to use QT plug in for VisStudio 2012. I used a file browser once the browse button is pressed everything works fine and I select my file. Right after the process with my file is completed, another file browser pops up... Can you help me? Here is the code:
#include "istorm__v3.h"
#include <QFileDialog>
#include <QMessageBox>
#include "ui_istorm__v3.h"
#include "iStormParser.h"
using namespace std;
iStormParser * isp;
iSTORM__v3::iSTORM__v3(QWidget *parent)
: QMainWindow(parent)
{
isp=new iStormParser();
ui.setupUi(this);
//ui.pushButton->setAutoDefault(false);
connect(ui.pushButton, SIGNAL(ui.pushButton.clicked()), this, SLOT(ui.on_pushButton_clicked()));
}
iSTORM__v3::~iSTORM__v3()
{
}
void iSTORM__v3::on_pushButton_clicked()
{
QString filename = QFileDialog::getOpenFileName(this,
tr("Choose File"),
"D:\\Desktop\\iSTORM__v3\\iSTORM__v3\\",
"C Files (*.c);;H Files (*.h)");
string tmp=filename.toUtf8().constData();
unsigned found = tmp.find_last_of("/\\");
tmp=tmp.substr(found+1);
string data=isp->run("\\testFiles\\"+tmp);
ui.textEdit->setText( QString::fromStdString(data));
return;
}
This issue would probably happen if you either connect the slot to the corresponding signal twice, or you emit the same signal again in your slot invokation, or at least "quickly" somewhere after having the slot quit that would bring this user experience.

I would like to open and read a text file at program launch, using Qt

I would like to open a text file at program launch, using Qt. I would like the text to appear in the text field which is called textEdit.
It is a simple notepad program that I am changing into an app I want to do other special things.
How do I input a text file, say "text.txt" into my textEdit widget upon program launch? All of the text file.
Writing with C++.
Thanks.
#include <QFile>
#include <QTextStream>
QString fileName = "myFile.txt";
File* myFile = new QFile(fileName);
if (myFile->open(QIODevice::ReadOnly | QIODevice::Text)
{
QTextStream *myFileStream = new QTextStream(myFile);
while ( !(myFileStream->atEnd()) )
{
QString line = myFileStream->readLine();
textEdit->append(line);
}
}