I have tried the fellowing two methods but failed:
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
QPlatformNativeInterface *interface = QApplication::platformNativeInterface();
jobject activity = (jobject)interface->nativeResourceForIntegration("QtActivity");
Ok, I was in QT 5.2 and this worked for me:
first:
in your .pro:
QT += gui-private
now in your cpp:
#include <QAndroidJniObject>
#include <qpa/qplatformnativeinterface.h>
QAndroidJniObject getMainActivity()
{
QPlatformNativeInterface *interface = QApplication::platformNativeInterface();
QAndroidJniObject activity = (jobject)interface->nativeResourceForIntegration("QtActivity");
if(!activity.isValid())
qDebug()<<"CLASS NOT VALID!!!!!!!!";
else
qDebug()<<"HORRAY!";
return activity;
Related
If I run this constructor
USB::USB(){
serialPort = new QSerialPort();
serialPortInfo = new QSerialPortInfo();
}
From this class
#include <QSerialPort>
#include <QSerialPortInfo>
class USB {
public:
USB();
private:
QSerialPort* serialPort;
QSerialPortInfo* serialPortInfo;
};
Then I got the error
The program has unexpectedly finished.
If I comment the code
USB::USB(){
//serialPort = new QSerialPort();
//serialPortInfo = new QSerialPortInfo();
}
Then I get no errors at all.
Why does this happens? I have missed something?
I'm running QT5 at Windows 10.
This gives no errors. Getting information about the COM ports works.
USB::USB(QSerialPort* serialPort, const QSerialPortInfo& serialPortInfo){
this->serialPort = serialPort;
this->serialPortInfo = serialPortInfo;
}
I'm trying to make a folder selection dialog which looks like this:
The images come from this thread: can the Open File dialog be used to select a Folder?
I tried both QFileDialog::getExistingDirectory() and making an instance of QFileDialog and setting the properties. It just shows the Open File dialog with hidden files.
Try this one: QFileDialog::getExistingDirectory()
http://qt-project.org/doc/qt-4.8/qfiledialog.html#getExistingDirectory
http://doc.qt.io/qt-5/qfiledialog.html#getExistingDirectory
Both static methods open File selector in directory selection mode. If you don't like the look-n-feel of the opened dialog, you'll need to implement your own. By default Qt tries to open native one if possible, which should work in 99.9% of cases.
It seems that I have to answer myself.
I did it purely in Qt in the end, by making the entire dialog:
Header file:
#pragma once
#include <QtWidgets/QDialog>
class QTreeView;
class QFileSystemModel;
class QLineEdit;
class QPushButton;
class CDirSelectionDlg : public QDialog {
Q_OBJECT
public:
CDirSelectionDlg(const QString initialPath, QWidget *parent = nullptr);
QDir directory() const;
private:
void onCurrentChanged();
QTreeView *m_treeView;
QFileSystemModel *m_model;
QLineEdit *m_folderName;
QPushButton *m_OKbutton;
QString m_initialPath;
};
Source file:
#include "DirSelectionDlg.h"
#include <QLabel>
#include <QBoxLayout>
#include <QDialogButtonBox>
#include <QTreeView>
#include <QFileSystemModel>
#include <QPushButton>
#include <QLineEdit>
CDirSelectionDlg::CDirSelectionDlg(const QString initialPath, QWidget *parent) : QDialog(parent), m_initialPath(initialPath)
{
setMinimumSize(200, 300);
resize(400, 430);
m_model = new QFileSystemModel(this);
auto rootIdx = m_model->setRootPath(m_initialPath);
m_treeView = new QTreeView(this);
m_treeView->setModel(m_model);
m_treeView->setSelectionMode(QAbstractItemView::SingleSelection);
m_treeView->setHeaderHidden(true);
m_treeView->setSortingEnabled(true);
m_treeView->sortByColumn(0, Qt::AscendingOrder);
for(int i = 1; i < m_model->columnCount(); i ++) // don't show Size, Type, etc.
m_treeView->setColumnHidden(i, true);
m_treeView->scrollTo(rootIdx);
m_treeView->selectionModel()->setCurrentIndex(rootIdx, QItemSelectionModel::Current | QItemSelectionModel::Select);
connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CDirSelectionDlg::onCurrentChanged);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &CDirSelectionDlg::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &CDirSelectionDlg::reject);
m_OKbutton = buttonBox->button(QDialogButtonBox::Ok);
auto label = new QLabel(tr("Folder:"));
m_folderName = new QLineEdit(this);
m_folderName->setReadOnly(true);
m_folderName->setText(QFileInfo(m_initialPath).fileName());
auto pathLayout = new QHBoxLayout();
pathLayout->addWidget(label);
pathLayout->addSpacing(10);
pathLayout->addWidget(m_folderName);
auto mainLayout = new QVBoxLayout();
mainLayout->addWidget(m_treeView);
mainLayout->addSpacing(10);
mainLayout->addLayout(pathLayout);
mainLayout->addSpacing(10);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
}
void CDirSelectionDlg::onCurrentChanged()
{
auto fileInfo = m_model->fileInfo(m_treeView->selectionModel()->currentIndex());
m_folderName->setText(fileInfo.fileName());
m_OKbutton->setEnabled(fileInfo.isDir());
m_OKbutton->setDefault(fileInfo.isDir());
}
QDir CDirSelectionDlg::directory() const
{
return QDir(m_model->fileInfo(m_treeView->selectionModel()->currentIndex()).absoluteFilePath());
}
I'm using Qt 5.3.1.
It's 7 years later, but I had the same need, in this case using Python 3.8 and Qt 5.13.2, so I translated Andrej's code for PySide2. I figured this might be useful for someone else having this problem.
Even though it is not a native Windows widget, I think it looks decent on both Windows and Linux. I decided to change the type of the return value of directory() and the initial_path parameter to pathlib.Path for my application.
class DirectorySelectionDialog(QDialog):
def __init__(self, initial_path: Path, parent: QWidget) -> None:
super().__init__(parent=parent)
self.initial_path = initial_path
self.setMinimumSize(200, 300)
self.resize(400, 430)
self.model = QFileSystemModel(parent=self)
self.model.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
root_index = self.model.setRootPath(str(self.initial_path))
self.tree_view = QTreeView(parent=self)
self.tree_view.setModel(self.model)
self.tree_view.setSelectionMode(QAbstractItemView.SingleSelection)
self.tree_view.setHeaderHidden(True)
self.tree_view.setSortingEnabled(True)
self.tree_view.sortByColumn(0, Qt.AscendingOrder)
for i in range(1, self.model.columnCount()):
self.tree_view.setColumnHidden(i, True)
self.tree_view.scrollTo(root_index)
self.tree_view.selectionModel().setCurrentIndex(root_index, QItemSelectionModel.Current | QItemSelectionModel.Select)
self.tree_view.selectionModel().selectionChanged.connect(self.onCurrentChanged)
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
self.ok_button = button_box.button(QDialogButtonBox.Ok)
label = QLabel("Folder:")
self.folder_name = QLineEdit(parent=self)
self.folder_name.setReadOnly(True)
self.folder_name.setText(self.initial_path.name)
path_layout = QHBoxLayout()
path_layout.addWidget(label)
path_layout.addSpacing(10)
path_layout.addWidget(self.folder_name)
main_layout = QVBoxLayout()
main_layout.addWidget(self.tree_view)
main_layout.addSpacing(10)
main_layout.addLayout(path_layout)
main_layout.addSpacing(10)
main_layout.addWidget(button_box)
self.setLayout(main_layout)
def onCurrentChanged(self):
file_info = self.model.fileInfo(self.tree_view.selectionModel().currentIndex())
self.folder_name.setText(file_info.fileName())
self.ok_button.setEnabled(file_info.isDir())
self.ok_button.setDefault(file_info.isDir())
def directory(self) -> Path:
file_info = self.model.fileInfo(self.tree_view.selectionModel().currentIndex())
return Path(file_info.absoluteFilePath())
I need to make some unit test for my school project in Qt and although I have read Qt tutorial on that I can't figure out how am I supposed to write such tests. All of tests shown in tutorial I've mentioned refer to built-in methods. How should I write a unit test for a custom class say this is the simplest class I have:
task.h
#ifndef TASK_H
#define TASK_H
#include <QDateTime>
#include <QTime>
class Task
{
private:
bool ifDone;
QString name;
QString description;
QDateTime *startTime;
QTime *start;
QDateTime *endTime;
QTime *end;
bool neededReminder;
QDateTime *reminderTime;
public:
Task(QString _name, QString _description, QDate *dayClicked,
QTime *_startTime, QTime *_endTime, bool reminder);
QString toString();
};
#endif // TASK_H `
task.cpp
#include "task.h"
Task::Task(QString _name, QString _description, QDate *dayClicked,
QTime *_startTime, QTime *_endTime, bool reminder)
{
ifDone = 0;
name = _name;
description = _description;
start = _startTime;
end = _endTime;
startTime = new QDateTime(*dayClicked, *start);
endTime = new QDateTime(*dayClicked, *end);
neededReminder = reminder;
}
QString Task::toString() {
QString task;
task.append(this->name);
task.append(" ");
task.append(this->start->toString("HH:mm"));
task.append(" - ");
task.append(this->end->toString("HH:mm"));
return task;
}
I was trying to #include this class to testing class as well as adding both .h and .cpp files to the project and I didn't manage to do anything. Can anyone write some sample testing methods (for toString method and constructor) for the above class so I could carry on myself with the rest. Thanks in advance.
To be sincere, I think this question should be closed and that you should start reading some of the books you've been provided. Also, I don't see what there is to test here, maybe the result of the string? However, see if this helps you:
UnitTests.pro
QT += testlib
QT -= gui
TARGET = tst_unitteststest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += tst_unitteststest.cpp task.cpp
DEFINES += SRCDIR=\\\"$$PWD/\\\"
HEADERS += task.h
tst_unitteststest.cpp
#include <QString>
#include <QtTest>
#include "task.h"
class UnitTestsTest : public QObject
{
Q_OBJECT
public:
UnitTestsTest();
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void testCase1();
};
UnitTestsTest::UnitTestsTest()
{
}
void UnitTestsTest::initTestCase()
{
}
void UnitTestsTest::cleanupTestCase()
{
}
void UnitTestsTest::testCase1()
{
QVERIFY2(true, "Failure");
Task t("name", "desc", new QDate(1, 1, 2012), new QTime(0, 0), new QTime(1, 0), false);
QVERIFY(t.toString() == "name 00:00 - 01:00");
}
QTEST_APPLESS_MAIN(UnitTestsTest)
#include "tst_unitteststest.moc"
Consider that there are mem leaks here... but I don't know how you want your class to become. The test will pass here of course.
I try to develop a Qt GUI application which will communicate with a board using USB. The library I use is libusb-win32 v1.2.5.0.
When I compile the application, the following errors occur:
./debug/thread_usb_comm.o: In function `ZN15thread_usb_comm15find_usb_deviceEtt':
thread_usb_comm.cpp:15: undefined reference to 'usb_find_busses'
thread_usb_comm.cpp:16: undefined reference to 'usb_find_devices'
thread_usb_comm.cpp:18: undefined reference to 'usb_get_busses'
thread_usb_comm.cpp:26: undefined reference to 'usb_open'
collect2: ld returned 1 exit status
mingw32-make[1]: [debug/CALSYS11_calib_app.exe] Error 1
mingw32-make: [debug] Error 2
The application code is:
(header file)
#ifndef THREAD_USB_COMM_H
#define THREAD_USB_COMM_H
#include <QThread>
#include <QtDebug>
#include "CALSYS11.h"
#include <lusb0_usb.h>
class thread_usb_comm : public QThread
{
Q_OBJECT
public:
thread_usb_comm();
private:
bool device_connected;
usb_dev_handle *p_usb_device;
bool find_usb_device(
unsigned short vendor_id,
unsigned short product_id
);
};
#endif // THREAD_USB_COMM_H
(source file)
#include "thread_usb_comm.h"
thread_usb_comm::thread_usb_comm()
{
device_connected = false;
}
bool thread_usb_comm::find_usb_device(
unsigned short vendor_id,
unsigned short product_id
)
{
struct usb_bus *bus;
struct usb_device *dev;
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next)
{
for (dev = bus->devices; dev; dev = dev->next)
{
if ((dev->descriptor.idVendor == vendor_id) &&
(dev->descriptor.idProduct == product_id))
{
qDebug ("Device found");
p_usb_device = usb_open(dev);
if (0 == p_usb_device)
{
qCritical ("Could not open USB device");
return false;
}
device_connected = true;
return true;
}
}
}
qDebug ("Cannot find specified device");
return false;
}
I added the link to the libusb library in the .pro file:
LIBS += -L\path\to\libusb-win32\lib\gcc -lusb
I develop on Windows 7.
Thank you,
Johann
Try to build release instead of debug or the static library is incompatible with compiler version (I faced same issue when I tried to build old static library with MinGW 4.4)
I am working on building a GUI around a console application. I would like to be able to click a button to run the console app and show the console output inside of the GUI itself. How might I accomplish this? I am working in Linux.
You could also try QProcess. It provides a Qt interface to launching external processes, reading their I/O and waiting, or not, on their completion.
For your purpose, it sounds like you want the process to run asynchronously, so code might look like :
myprocessstarter.h :
#include <QObject>
#include <QProcess>
#include <QDebug>
class MyProcessStarter : public QObject
{
Q_OBJECT
public:
MyProcessStarter() : QObject() {};
void StartProcess();
private slots:
void readStandardOutput();
private:
QProcess *myProcess;
};
main.cpp:
#include "myprocessstarter.h"
void MyProcessStarter::StartProcess()
{
QString program = "dir";
QStringList arguments;
// Add any arguments you want to be passed
myProcess = new QProcess(this);
connect(myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
myProcess->start(program, arguments);
}
void MyProcessStarter::readStandardOutput()
{
QByteArray processOutput;
processOutput = myProcess->readAllStandardOutput();
qDebug() << "Output was " << QString(processOutput);
}
void main(int argc, char** argv)
{
MyProcessStarter s;
s.StartProcess();
}
I wanted to do something similar in one of my applications. I redirected all output from the standard stream (cout) to my console window. To periodically read out the stream contents I use a timer loop. Works fine for me.
StdRedirector.cpp
#include "StdRedirector.h"
QMutex coutMutex;
void outcallback(const char* ptr, std::streamsize count, void* bufferString)
{
string *b = (string *) bufferString;
string t;
for (int i=0; i < count; i++)
{
if (ptr[i] == '\n')
{
t = t + "\n";
} else {
t = t + ptr[i];
}
}
coutMutex.lock();
*b = *b + t;
coutMutex.unlock();
}
void ConsoleWindow::updateTimer(void)
{
coutMutex.lock();
if (bufferString.size() > 0)
{
consoleBox->insertPlainText(QString(bufferString.c_str()));
bufferString.clear();
QScrollBar *sb = consoleBox->verticalScrollBar();
sb->setValue(sb->maximum());
}
coutMutex.unlock();
}
ConsoleWindow::ConsoleWindow(QWidget *parent) : QWidget(parent)
{
consoleBox = new QTextEdit(this);
consoleBox->setReadOnly(true);
stdRedirector = new StdRedirector<>(std::cout, outcallback, &bufferString);
QVBoxLayout *vb = new QVBoxLayout();
vb->addWidget(consoleBox);
vb->setMargin(0);
vb->setSpacing(0);
setLayout(vb);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateTimer()));
timer->start(100);
}
ConsoleWindow::~ConsoleWindow()
{
delete stdRedirector;
}
StdRedirector.h
#ifndef STD_REDIRECTOR
#define STD_REDIRECTOR
#include <QWidget>
#include <QTextEdit>
#include <QString>
#include <QVBoxLayout>
#include <QTimer.h>
#include <QMutex>
#include <QScrollBar>
#include <iostream>
#include <string>
using namespace std;
template<class Elem = char, class Tr = std::char_traits<Elem>>
class StdRedirector : public std::basic_streambuf<Elem, Tr>
{
typedef void (*pfncb) ( const Elem*, std::streamsize _Count, void* pUsrData );
public:
StdRedirector(std::ostream& a_Stream, pfncb a_Cb, void* a_pUsrData) :
m_Stream(a_Stream),
m_pCbFunc(a_Cb),
m_pUserData(a_pUsrData)
{
m_pBuf = m_Stream.rdbuf(this);
}
~StdRedirector()
{
m_Stream.rdbuf(m_pBuf);
}
std::streamsize xsputn(const Elem* _Ptr, std::streamsize _Count)
{
m_pCbFunc(_Ptr, _Count, m_pUserData);
return _Count;
}
typename Tr::int_type overflow(typename Tr::int_type v)
{
Elem ch = Tr::to_char_type(v);
m_pCbFunc(&ch, 1, m_pUserData);
return Tr::not_eof(v);
}
protected:
std::basic_ostream<Elem, Tr>& m_Stream;
std::streambuf* m_pBuf;
pfncb m_pCbFunc;
void* m_pUserData;
};
class ConsoleWindow : public QWidget
{
Q_OBJECT
public:
ConsoleWindow(QWidget *parent = 0);
~ConsoleWindow();
public slots:
void updateTimer(void);
public:
QTextEdit *consoleBox;
StdRedirector<> *stdRedirector;
string bufferString;
};
#endif
The StdRedirector class is based on code from this forum post: http://www.qtforum.org/article/24554/displaying-std-cout-in-a-text-box.html
Take a look at the popen() function, it might do what you need.
Then you could pass the FILE * to a QTextStream and work in Qt style with it.
I suggest, rather than showing stdout in GUI, having own console output, which essentially means all messages you want to show to users you are sending to your own output.
This way you can have debug messages and such still available from console, wtih potential errors with connections and whatever that can happen and have fully controlled console output in GUI application. Of course this output can also be outputted to stdout so it is visible in console, but it also allows you to append a prefixs like WARNING LOG NOTICE NO_THIS_WENT_WRONG or whatever you want to show to users as your console entry.