How to copy local file to QClipboard (in Gnome)? - qt

QClipboard offers several ways to copy stuff into the clipboard. There are high level functions for standard desktop (text, pixmaps, etc), but I could not figure out how to implement the standard copy file operation. Google did not help.

Just put appropriate mime type and URL of the local file into clipboard. Docs reference.
QMimeData* mimeData = new QMimeData();
mimeData->setData("text/uri-list", "file:///C:/fileToCopy.txt");
clipboard->setMimeData(mimeData);
You can use static method QUrl::fromLocalFile to get QUrl instance to be used in mimeData->setData :
mimeData->setData("text/uri-list", QUrl::fromLocalFile("C:/fileToCopy.txt"));

Okay I found the solution to my problem. The problem is that gnome (working on linux) does its own thing. The file(s) are not stored in the text/uri-list format like N1ghtLight mentioned, but uses the special x-special/gnome-copied-files format. The following code did it:
// Get clipboard
QClipboard *cb = QApplication::clipboard();
// Ownership of the new data is transferred to the clipboard.
QMimeData* newMimeData = new QMimeData();
// Copy old mimedata
const QMimeData* oldMimeData = cb->mimeData();
for ( const QString &f : oldMimeData->formats())
newMimeData->setData(f, oldMimeData->data(f));
// Copy path of file
newMimeData->setText(_file->absolutePath());
// Copy file
newMimeData->setUrls({QUrl::fromLocalFile(_file->absolutePath())});
// Copy file (gnome)
QByteArray gnomeFormat = QByteArray("copy\n").append(QUrl::fromLocalFile(_file->absolutePath()).toEncoded());
newMimeData->setData("x-special/gnome-copied-files", gnomeFormat);
// Set the mimedata
cb->setMimeData(newMimeData);

Related

Qt. Problem with the QFileDialog: setDirectory() and directory()

I have a problem with the QFileDialog class, namely with the setDirectory() and directory() methods. I need to make it so that after opening a file, my program remembers the directory in which the selected file is stored, and the next time QFileDialog is called, it automatically opens the directory that was used last. Here is a snippet of my code:
static QString _st_doc_last_directory;
void MainWindow::open()
{
if (!fileDialog)
{ fileDialog = new QFileDialog(this);
}
if (!_st_doc_last_directory.isEmpty()) fileDialog->setDirectory(_st_doc_last_directory);
QString fileName = fileDialog->getOpenFileName(this, tr("Open Document"), ".", tr("Compressed CAD Models (*.data)"));
if (!fileName.isEmpty())
{ _st_doc_last_directory = fileDialog->directory().dirName();
}
}
The crux of my problem is that when the setDirectory() or directory() method is called, my program crashes with a
"Segmentation fault"
message. How can I fix it, please advise. Thanks in advance.
Whenever you start this method, you have this as the start window: ".". (admittedly I don't know what's going on internally, but I think this leads to this problem).
You can query beforehand whether your defined string is empty. if so you set a path, otherwise you store one in your string. If you don't want to do this from the beginning every time you start the program, you can also use QSettings. This saves you the path in the registry (ie if you use windows).
With QFileInfo you can easily get the path
void MainWindow::open()
{
if(_st_doc_last_directory.isEmpty())
_st_doc_last_directory = QDir::homePath();
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Document"), _st_doc_last_directory, tr("Compressed CAD Models (*.data)"));
QFileInfo info(fileName);
if(!fileName.isEmpty())
_st_doc_last_directory = info.absolutePath();
}

Make the difference between a file path and a url in Qt

If I have a string which could be either a file or a URL, is there any existing clever method I could use to differentiate them?
For instance:
/Users/user/Documents/mydoc.txt -> path
c:\Program Files\myapp\mydoc.doc -> path
https://mywebsite.com/mydoc.txt -> url
ftp://myserver.com/myfile.txt -> url
This is to load a designer UI file, so I need to make a local temporary copy of the remote file.
So the bottom line is to know when I need to download the file.
Well, you might want to construct a QUrl object out of these strings and verify whether these URLs refer to local files. I.e.:
static bool isLocalFile(const QString &str)
{
return QUrl::fromUserInput(str).isLocalFile();
}
With your strings
QString s1("/Users/user/Documents/mydoc.txt");
QString s2("c:\\Program Files\\myapp\\mydoc.doc");
QString s3("https://mywebsite.com/mydoc.txt");
QString s4("ftp://myserver.com/myfile.txt");
bool b = isLocalFile(s1); // a path
b = isLocalFile(s2); // a path
b = isLocalFile(s3); // not a path
b = isLocalFile(s4); // not a path
You could create a QFile with the given name and check if it exists(). If not try to resolve string as a URL.

BitmapFactory.decodeStream returns null reading local file

A quick summary of my problem: I am trying to read a local image file. If I include the file in my assets directory and treat it as an asset everything works fine. However, if I try to read it from the external sd card, BitmapFactory.decode stream returns null.
I've had the same results with both .jpeg and .png files.
This is how I obtain an InputStream from the asset file:
InputStream isa = context.getAssets().open("Boulder.jpg");
This is how I obtain an InputStream from the asset file:
File f = new File( "/mnt/extSdCard/Maps/Colorado/Boulder.jpg" );
InputStream isf = new BufferedInputStream( new FileInputStream( f.toString() ) );
In either case the InputStream is passed to this code: (If this code looks familiar, it was borrowed from an internet example)
this.decoder = BitmapRegionDecoder.newInstance(inputStream, false);
tmpOptions.inJustDecodeBounds = true;
Bitmap temp = BitmapFactory.decodeStream(inputStream, null, tmpOptions);
setSceneSize(tmpOptions.outWidth, tmpOptions.outHeight);
tmpOptions.inJustDecodeBounds = false;
tmpOptions.inSampleSize = (1<<downShift);
sampleBitmap = BitmapFactory.decodeStream(inputStream, null, tmpOptions);
Again, using the asset file derived InputStream, everything works fine. Conversely, with the sdCard file, outWidth and outHeight are both -1 after the first call and sampleBitmap is null after the second.
I'm really wrapped around the axle on with this problem and have spent a lot of time browsing this forum and experimenting with suggested solutions all to no avail. I also wrote some test code which opened both versions of the file, creating InputStreams as shown above, then read the contents of each stream and compared each byte and found them to be identical.
I've tried the code on different devices with the same results. I'm currently testing on a Galaxy Note II (Android 4.1.1) with the following version info in the AndroidManifest:
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
I need the ability to dynamically add files to the system so including everything as an asset is not an option. Any help would be greatly appreciated.
You can simple use
BitmapFactory.decodeFile(file.getAbsolutePath(), tmpOptions);
rather than
File f = new File( "/mnt/extSdCard/Maps/Colorado/Boulder.jpg" );
InputStream isf = new BufferedInputStream( new FileInputStream( f.toString() ) );
BitmapFactory.decodeStream(inputStream, null, tmpOptions)

How do I read in FILE contents in QML?

I just need something similar to Fstream to read file IO in QML. Why is there no file IO?
If your file is plain text you can use XMLHttpRequest. For example:
var xhr = new XMLHttpRequest;
xhr.open("GET", "mydir/myfile.txt");
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var response = xhr.responseText;
// use file contents as required
}
};
xhr.send();
I know this is old question but you might be still interested in answer.
Here it is: Reading a line from a .txt or .csv file in qml (Qt Quick)
In short, you have here explained how to read files in QML: http://www.developer.nokia.com/Community/Wiki/Reading_and_writing_files_in_QML
All you need is to extend QML with C++.
QML has no built-in file I/O. But - judging from the tone of your post - you already knew that.
How do I read in FILE contents in QML?
You can extend QML's functionalities using C++.
The Getting Started Programming with QML tutorial from the Qt Reference Documentation shows you how to build a text editor. This includes file I/O using C++.
Why is there no file I/O?
Because QML is based on JavaScript, and JavaScript has no built-in file I/O either.
QML is designed as an (easy) way to build a user interface. You need an actual program to do the rest.
There is built-in file I/O available for QML with the Felgo SDK (formerly V-Play) FileUtils. It works cross-platform on desktop, iOS and Android. More info and examples are also in the latest blog post.
It looks like this:
var documentsData = fileUtils.readFile("subfolder/file.json")
function readConfigFile() {
var xhr = new XMLHttpRequest;
var configaddress = "File:///" + root + "/webconfig.txt" //root = "c:/folder/file.ini";
console.log(configaddress);
xhr.open("GET", configaddress);
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var response = xhr.responseText;
var js = JSON.parse(response)
if (js.address != "") {
service_address = js.address
}
// use file contents as required
}
};
xhr.send();
}
What do you want to read the file for?... if its simple data.. then you are probably better off using QML Offline storage API. Look for that section here.
If you want to deploy a db with your application read this conversation.
If you really want to read the file still, learn C++ and expose your code to QML. That, then, is beyond the scope of my answer.

Qt: opening qrc pdf with the poppler library

I'm having a bit of trouble with my function for displaying pdf's with the poppler library. The code below is the function in which the problem occurs.
const QString &file is the path to the file
int page is the page on which it has to open
When i set file to a real path (e.g. "/Users/User/Documents/xxx.pdf"), it is no problem to open it. But when i give the path to a qrc file (":/files/xxx.pdf"), it won't work. I want to use it for displaying a user manual for instance, within the application.
I've also tried first making a QFile out of it, opening it and doing readAll, then loading the QByteArray received by doingPoppler::Document::loadFromData(the qbytearray), but it errors already when opening the QFile in ReadOnly mode.
void class::setPdf(const QString &file, int page)
{
Poppler::Document *doc = Poppler::Document::load(file);
if (!doc) {
QMessageBox msgbox(QMessageBox::Critical, tr("Open Error"), tr("Please check preferences: cannot open:\n") + file,
QMessageBox::Ok, this);
msgbox.exec();
}
else{ /*Code for displaying the pdf, which works fine*/
}
}
I hope you can help me,
greetings,
Matt
I've also tried first making a QFile
out of it, opening it and doing
readAll, then loading the QByteArray
received by
doingPoppler::Document::loadFromData(the
qbytearray), but it errors already
when opening the QFile in ReadOnly
mode.
QFile f;
f.setFileName(":/skin/AppIcon16.png");
f.open(QIODevice::ReadOnly);
QByteArray r=f.readAll();
Perfectly reads all data from the resource, have checked it. So i suggest you did something wrong when tried that. Maybe path errors, maybe something else...

Resources