how can i get file dropped to which gtkmm image widget - c++

....
std::vector<Gtk::TargetEntry> listTargets;
listTargets.push_back( Gtk::TargetEntry("STRING") );
listTargets.push_back( Gtk::TargetEntry("text/plain") );
image1->drag_dest_set(listTargets);
image1->signal_drag_data_received().connect(sigc::mem_fun(*this,
&mainWindow::drop_event) );
image2->drag_dest_set(listTargets);
image2->signal_drag_data_received().connect(sigc::mem_fun(*this,
&mainWindow::drop_event) );
....
and my drop&drop event handler function :
void mainWindow::drop_event(
const Glib::RefPtr<Gdk::DragContext>& context, int, int,
const Gtk::SelectionData& selection_data, guint, guint time)
{
std::cout << selection_data.get_data_as_string() << std::endl;
}
I can get file locations that "dragged to image widgets" with this code. output is like this:
file:////opt/google/chrome/google-chrome.desktop
file:////var/www/index.html
file:///opt/libreoffice4.1/LICENSE.html
it's ok, i can. But, how can i get: file dropped to which image (image1 or image2 widgets) like this:
dropped to **image1** : file:////opt/google/chrome/google-chrome.desktop
dropped to **image2** : file:////var/www/index.html
dropped to **image1** : file:///opt/libreoffice4.1/LICENSE.html
thanks...

sigc allows you to bind extra arguments to your handlers.
Hander becomes:
void mainWindow::drop_event(
const Glib::RefPtr<Gdk::DragContext>& context, int, int,
const Gtk::SelectionData& selection_data, guint, guint time,
Glib::ustring whichImage)
{
std::cout << "dropped to" << whichImage << ":" << selection_data.get_data_as_string() << std::endl;
}
And the connect then is:
image1->signal_drag_data_received().connect(sigc::bind<Glib::ustring>(sigc::mem_fun(*this,
&mainWindow::drop_event), "image1" ));
image2->signal_drag_data_received().connect( sigc::bind<Glib::ustring>(sigc::mem_fun(*this,
&mainWindow::drop_event), "image2"));

Related

Error handling design: Bind error messages to error codes

I have a simple structures to handle errors
enum class Error
{
None = 0,
FirstError,
SecondError,
ThirdError,
...
}
struct ErrorCategory
{
static const std::string& Message(Error aError)
{
static const std::string messages[] =
{
"first error message",
"second error message",
"third error message",
...
}
const auto index = static_cast<size_t>(aError);
assert(index < std::size(messages) && "Invalid error");
return messages[index];
}
};
Also, there are some class and methods to work with those structures.
Though it works, but the amount of errors is growing, so it becomes hard to navigate between error messages and error codes in enum. I want to declare error code and message for it in one place to make it easy to find error code. Is there a way to do it without making my code huge (such as enum + switch cases for messages) so it would be easy to maintain and without using macro?
You can use std::map<Error, std::string> like:
enum class Error : uint8_t {
None = 0,
FirstError = 1,
SecondError = 2,
ThirdError = 3
};
std::map<Error, std::string> error_messages = {
{ Error::None, "unknown error message" },
{ Error::FirstError, "first error message" },
{ Error::SecondError, "second error message" },
{ Error::ThirdError, "third error message" }
};
and then use it afterwards like:
std::cerr << error_messages[Error::None] << std::endl;
std::cerr << error_messages[Error::FirstError] << std::endl;
std::cerr << error_messages[Error::SecondError] << std::endl;
std::cerr << error_messages[Error::ThirdError] << std::endl;
Demo
This type of operation is exactly how most localized UIs work. You map some common structured ID to a user-facing string.
Because of this, there are a huge amount of platform-specific ways of doing this which aim to do exactly what you want. For example on Windows:
(Windows) FormatMessage and Message Compiler
(Windows / .NET) .resx files and ResourceManager

QLibrary functions work slow on first call

I'm using QLibrary to load functions from one .dll file.
I succesfully load it, succesfully resolve functions.
But when i use some function from that .dll for the first time, this function works very slow(even if it is very simple one). Next time i use it again - and the speed is just fine (immediately, as it should be).
What is the reason for such behaviour? I suspect some caсhing somewhere.
Edit 1: Code:
typedef int(*my_type)(char *t_id);
QLibrary my_lib("Path_to_lib.dll");
my_lib.load();
if(my_lib.isLoaded){
my_type func = (my_type)my_lib.resolve("_func_from_dll");
if(func){
char buf[50] = {0};
char buf2[50] = {0};
//Next line works slow
qint32 resultSlow = func(buf);
//Next line works fast
qint32 resultFast = func(buf2);
}
}
I wouldn't blame QLibrary: func simply takes long the first time it's invoked. I bet that you'll have identical results if you resolve its address using platform-specific code, e.g. dlopen and dlsym on Linux. QLibrary doesn't really do much besides wrapping the platform API. There's nothing specific to it that would make the first call slow.
There is some code smell of doing file I/O in constructors of presumably generic classes: do the users of the class know that the constructor may block on disk I/O and thus ideally shouldn't be invoked from the GUI thread? Qt makes the doing this task asynchronously fairly easy, so I'd at least try to be nice that way:
class MyClass {
QLibrary m_lib;
enum { my_func = 0, other_func = 1 };
QFuture<QVector<FunctionPointer>> m_functions;
my_type my_func() {
static my_type value;
if (Q_UNLIKELY(!value) && m_functions.size() > my_func)
value = reinterpret_cast<my_type>(m_functions.result().at(my_func));
return value;
}
public:
MyClass() {
m_lib.setFileName("Path_to_lib.dll");
m_functions = QtConcurrent::run{
m_lib.load();
if (m_lib.isLoaded()) {
QVector<QFunctionPointer> funs;
funs.push_back(m_lib.resolve("_func_from_dll"));
funs.push_back(m_lib.resolve("_func2_from_dll"));
return funs;
}
return QVector<QFunctionPointer>();
}
}
void use() {
if (my_func()) {
char buf1[50] = {0}, buf2[50] = {0};
QElapsedTimer timer;
timer.start();
auto result1 = my_func()(buf1);
qDebug() << "first call took" << timer.restart() << "ms";
auto result2 = my_func()(buf2);
qDebug() << "second call took" << timer.elapsed() << "ms";
}
}
};

How can I add the console (stdout) as a sink in g3log?

I am new to g3log. I compiled and ran one of the examples I found in the repo, but was not able to ,modify it to print the log messages to the console rather than a file.
The following lines from the example set the logger:
auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(argv[0], path_to_log_file);
g3::initializeLogging(worker.get());
Where the line in the middle sets the prefix of the log and gives the path where the log file should be created.
How can I modify this code to print to the console\both the console and the file?
Thanks,
Omer.
You could define a customized sink class with a message receiver function that forward the
stripped message to console without formatting. Below is simplest form of the implementation:
class CustomSink {
public:
void forwardLogToStdout(g3::LogMessageMover logEntry) {
std::cout << logEntry.get().message() << std::endl;
}
};
So, in your code, you only need to replacing the worker->addDefaultLogger(...) by this snippet:
auto handle = worker->addSink(std::make_unique<CustomSink>(), &CustomSink::forwardLogToStdout);
from g3log github to implement colored console output you need:
struct ColorCoutSink {
// Linux xterm color
// http://stackoverflow.com/questions/2616906/how-do-i-output-coloured-text-to-a-linux-terminal
enum FG_Color {YELLOW = 33, RED = 31, GREEN=32, WHITE = 97};
FG_Color GetColor(const LEVELS level) const
{
if (level.value == WARNING.value) { return YELLOW; }
if (level.value == DEBUG.value) { return GREEN; }
if (g3::internal::wasFatal(level)) { return RED; }
return WHITE;
}
void ReceiveLogMessage(g3::LogMessageMover logEntry)
{
auto level = logEntry.get()._level;
auto color = GetColor(level);
std::cout << "\033[" << color << "m" << logEntry.get().toString() << "\033[m" << std::endl;
}
};
// in main.cpp, main() function
auto sinkHandle = logworker->addSink(std::make_unique<CustomSink>(),
&CustomSink::ReceiveLogMessage);
So if you remove color "things", the logger will output to console

Reading *.mhd/*.raw format 3D images in ITK

How to load and write .mhd/.raw format 3D images in ITK? I have tried to use the following code but it is not getting loaded as the dimension of the loaded image is displayed as 0,0,0.
Can someone please point out the mistake I am making?
typedef float InputPixelType;
const unsigned int DimensionOfRaw = 3;
typedef itk::Image< InputPixelType, DimensionOfRaw > InputImageType;
//typedef itk::RawImageIO<InputPixelType, DimensionOfRaw> ImageIOType;
typedef itk::ImageFileReader<InputImageType > ReaderType;
/*
* --------------------Loader and saver of Raws, as well the function that takes a resulting (from inference matrix/vector) and creates a Raw out of it.-----------------------
*/
InputImageType::Pointer loadRawImageItk( std::string RawFullFilepathname, ReaderType::Pointer & RawImageIO ) {
//http://www.itk.org/Doxygen/html/classitk_1_1Image.html
//http://www.itk.org/Doxygen/html/classitk_1_1ImageFileReader.html
typedef itk::ImageFileReader<InputImageType> ReaderType;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName(RawFullFilepathname);
//ImageIOType::Pointer RawImageIO = ImageIOType::New();
reader->SetImageIO( RawImageIO );
try {
reader->Update();
} catch (itk::ExceptionObject& e) {
std::cerr << e.GetDescription() << std::endl;
exit(1); // You can choose to do something else, of course.
}
//InputImageType::Pointer inputImage = reader->GetOutput();
InputImageType::Pointer inputImage = reader->GetOutput();
return inputImage;
}
int saveRawImageItk( std::string RawFullFilepathname, InputImageType::Pointer & outputImageItkType , ImageIOType::Pointer & RawImageIO) {
std::cout << "Saving image to: " << RawFullFilepathname << "\n";
typedef itk::ImageFileWriter< InputImageType > Writer1Type;
Writer1Type::Pointer writer1 = Writer1Type::New();
writer1->SetInput( outputImageItkType );
writer1->SetFileName( RawFullFilepathname );
writer1->SetImageIO( RawImageIO ); //seems like this is useless.
// Execution of the writer is triggered by invoking the \code{Update()} method.
try
{
writer1->Update();
}
catch (itk::ExceptionObject & e)
{
std::cerr << "exception in file writer " << std::endl;
std::cerr << e.GetDescription() << std::endl;
std::cerr << e.GetLocation() << std::endl;
return 1;
}
return 0;
}
I have just read the mhd and raw files in Python successfully using the following SimpleITK code:
import SimpleITK as sitk
import numpy as np
def load_itk_image(filename):
itkimage = sitk.ReadImage(filename)
numpyImage = sitk.GetArrayFromImage(itkimage)
return numpyImage
Maybe you can use it as a reference.
Whether you should use the ReadImage function instead of the ImageFileReader? You can have a try.
A few good examples of file reading depending on a known format are found here.
reader->SetImageIO( RawImageIO );
seems the incorrect thing to do here if you are loading both .mhd and .raw files as they are seperate formats, MetaImage vs Raw format where you do and don't know the image size, origin, spacing etc based on the absense or presense of a header.
How are you determining the size of the image and getting (0,0,0)? image->GetSize()?
Can you provide test data?
https://itk.org/Wiki/ITK/Examples/IO/ReadUnknownImageType
https://itk.org/ITKExamples/src/IO/ImageBase/RegisterIOFactories/Documentation.html

Qt QDbus Sending Custom Types with QVariant

I'm trying to send a custom class ( "Span" ) inside a QVariant across the Dbus session bus in Qt between 2 simple applications. Span is a simple class that contains 2 double type properties. I have successfully sent and recovered a QVariant containing just a QString across the dbus interface in the same manner I am trying to do below with a QVariant of a custom class.
Span contains the following declaration for the QMETATYPE QVariant registration in the class header file:
Q_DECLARE_METATYPE(Span)
I have 2 test applications, one sender and one receiver - both have exactly the same 'Span' class definitions. In my sender app I do this:
qDebug() << "Sending QVariant Span to receiver...";
//int spanID = QMetaType::type("Span");
Span span(100,0.5);
//QVariant settingVariant(spanID, &span);
//QVariant settingVariant(QString("HELLO"));
QVariant settingVariant;
settingVariant.setValue(span);
QDBusVariant setting( settingVariant );
response = client->setSetting(setting);
qDebug() << "RESPONSE: " << response;
QVariant result = setting.variant(); // THIS WORKS - I can just extract my 'Span' here with the correct property values set
QVariant test = QVariant::fromValue(result);
Span testSpan = test.value<Span>();
qDebug() << "Setting Span to -- Low: " << testSpan.m_lowTemp
<< "High: " << testSpan.m_highTemp;
The 'setSetting' method is defined as:
inline QDBusPendingReply<int> setSetting(const QDBusVariant setting)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(setting);
return asyncCallWithArgumentList(QLatin1String("setSetting"), argumentList);
}
In the receiver, I register the 'Span' class like this:
qRegisterMetaType<Span>();
qDBusRegisterMetaType<Span>();
and then I attempt to recover the Span class like so:
int DbusServerTemplate::setSetting( const QDBusVariant &setting ) {
QVariant result = setting.variant();
QVariant test = QVariant::fromValue(result);
Span stuff = test.value<Span>();
qDebug() << "Setting Span to -- Low: " << stuff.m_low
<< "High: " << stuff.m_high;
The above code gives me bogus values for the Span class properties:
Setting Span to -- Low: 1.44144e-305 High: 5.24729e-261
What am I doing wrong? I can encode and decode the Span instance in the Sender app but once the receiver class gets it over dbus I'm getting bogus values. I'd really appreciate any ideas / help!
NOTE: I did implement the streaming operators in my Span class as follows ( the same class implementation is present in both the receiver and sender app ):
// Simple getters for the low and high temps
double Span::getHighTemp() const { return m_high; }
double Span::getLowTemp() const { return m_low; }
// Marshall the Data data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const Span &span)
{
argument.beginStructure();
double high = span.getHighTemp();
double low = span.getLowTemp();
argument << high;
argument << low;
argument.endStructure();
return argument;
}
// Retrieve the Data data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, Span &span)
{
double high, low;
argument.beginStructure();
argument >> high;
argument >> low;
argument.endStructure();
span.m_high = high;
span.m_low = low;
return argument;
}
I have got same issue. There must be
Span stuff = qdbus_cast<Span>(test);