Qt Drag and Drop a qgraphicsrectitem from one Graphicsview into another one - drag-and-drop

I want to drag and drop a custom QGraphicsRectItem from one Graphicsview into another. I tried it with the QGraphicsSceneDragDropEvents and the QDragEnterEvent,QDropEvent, etc.
(I know I donĀ“t need all of these includes).
Layout.h
#ifndef LAYOUT_H
#define LAYOUT_H
#include <QtWidgets/QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QtWidgets>
#include <QObject>
#include <QCursor>
#include <QDrag>
#include "ui_layout.h"
#include "GrRectItm_WorkRect.h"
#include <QGraphicsSceneDragDropEvent>
#include <QBrush>
#include <QGraphicsSceneDragDropEvent>
class Layout : public QObject, public QMainWindow
{
Q_OBJECT
public:
Layout(QWidget *parent = 0);
~Layout();
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
/*void dragEnterEvent(QGraphicsSceneDragDropEvent *event) ;
void dragMoveEvent(QGraphicsSceneDragDropEvent *event) ;
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) ;
void dropEvent(QGraphicsSceneDragDropEvent *event) ;*/
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
//void mousePressEvent(QMouseEvent *event);
private:
Ui::LayoutClass ui;
QGraphicsScene *tb;
QGraphicsScene *wa;
int mX;
int mY;
QPoint mousePosition;
QGraphicsRectItem *rect;
QBrush blueBrush = (Qt::blue);
QBrush redBrush = (Qt::red);
QBrush greenBrush = (Qt::green);
QPen blackPen = (Qt::black);
QBrush rectColor ;
QString str_text;
bool selected;
void newRect();
signals:
public slots:
void changeColor();
void changeText();
void deleteRect();
};
#endif // LAYOUT_H
Layout.cpp
#include "layout.h"
#include <QtWidgets>
#include <QGraphicsItem>
#include"GrRectItm_WorkRect.h"
#include <QGraphicsView>
GrRectItm_WorkRect *rectItem;
GrRectItm_WorkRect *location;
QList < GrRectItm_WorkRect *> items;
Layout::Layout(QWidget *parent)
: QMainWindow(parent)
{
qDebug() << "Programm startet";
ui.setupUi(this);
tb = new QGraphicsScene(this);
wa = new QGraphicsScene(this);
ui.gv_ToolBar->setScene(tb);
ui.gv_WorkArea->setScene(wa);
ui.gv_ToolBar->setAcceptDrops(true);
ui.gv_WorkArea->setAcceptDrops(true);
ui.gv_WorkArea->setDragMode(QGraphicsView::ScrollHandDrag);
blackPen.setWidth(1);
rect = tb->addRect(10, 0, 90, 50, blackPen, blueBrush);
//rect->setFlag(QGraphicsItem::ItemIsSelectable);
QObject::connect(ui.btn_Change, SIGNAL(clicked()), this,
SLOT(changeColor()));
QObject::connect(ui.btn_Delete, SIGNAL(clicked()), this, SLOT(deleteRect()));
}
//void Layout::dragEnterEvent(QGraphicsSceneDragDropEvent *event) {
void Layout::dragEnterEvent(QDragEnterEvent *event) {
qDebug() << "dragEnterEvent startet";
event->acceptProposedAction();
}
//void Layout::dragEnterEvent(QGraphicsSceneDragDropEvent *event) {
void Layout::dragMoveEvent(QDragMoveEvent *event) {
qDebug() << "dragMoveEvent startet";
event->acceptProposedAction();
}
void Layout::dropEvent(QDropEvent *event) {
//void Layout::dropEvent(QGraphicsSceneDragDropEvent *event) {
qDebug() << "dropEvent startet";
QRectF rect123(0, 0, 70, 40);
mX = mousePosition.x();
mY = mousePosition.y();
str_text = ui.le_Name->text();
rectItem = new GrRectItm_WorkRect(str_text);
//newRect();
wa->addItem(rectItem);
rectItem->setRect(rect123);
rectItem->setPos(mX, mY);
rectItem->setBrush(greenBrush);
items.append(rectItem);
}
//void Layout::mousePressEvent(QGraphicsSceneMouseEvent *event) {
void Layout::mousePressEvent(QMouseEvent *event) {
qDebug() << "MousePressEvent startet";
mousePosition = event->pos();
mousePosition = mapToParent(event->pos() - mousePosition);
//if (rect->contains(mousePosition)) {
QPixmap *pix = new QPixmap(100, 50);
pix->fill(Qt::red);
QDrag *drag = new QDrag(this);
QMimeData *mime = new QMimeData;
drag->setMimeData(mime);
drag->setPixmap(*pix);
Qt::DropAction dropAction = drag->exec();
//}
}
void Layout::newRect() {
QString color = ui.cb_color->currentText();
QString text = ui.le_Name->text();
if (color == "Rot") {
rectItem->setBrush(redBrush);
rectItem->GrRectItm_WorkRect::setRectText(text);
}
else if (color == "Gruen") {
rectItem->setBrush(greenBrush);
rectItem->GrRectItm_WorkRect::setRectText(text);
}
else if (color == "Blau") {
rectItem->setBrush(blueBrush);
rectItem->GrRectItm_WorkRect::setRectText(text);
}
}
void Layout::changeColor() {
QString color = ui.cb_color->currentText();
QString text = ui.le_Name->text();
for (int i = 0; i < items.length(); i++) {
location = items.at(i);
selected = location->isSelected();
if (selected) {
rectItem = items.at(i);
try
{
newRect();
}
catch (const std::exception&)
{
continue;
}
}
}
}
void Layout::deleteRect() {
for (int i = 0; i < items.length(); i++) {
rectItem = items.at(i);
selected = rectItem->isSelected();
if (selected) {
try
{
rectItem->~GrRectItm_WorkRect();
items.removeAt(i);
i--;
}
catch (const std::exception&)
{
continue;
}
}
}
}
void Layout::changeText() {
QString text = ui.le_Name->text();
rectItem->GrRectItm_WorkRect::setRectText(text);
}
void Layout::mouseReleaseEvent(QMouseEvent *event) {
mousePosition = event->pos() - mousePosition;
}
Layout::~Layout()
{
}

Related

How to define a static private method outside the class in c++

#include <iostream>
class BST {
private:
struct Bst_node
{
int data;
struct Bst_node* left;
struct Bst_node* right;
}*root;
// static Bst_node* get_inorder_predecessor(Bst_node* ptr);
static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr)
{
ptr = ptr->left;
if (ptr == NULL) return NULL;
while (ptr->right != NULL)
{
ptr = ptr->right;
}
return ptr;
}
public:
void create()
{
root = new Bst_node;
root->data = 8;
root->right = NULL;
root->left = new Bst_node;
root->left->data = 10;
root->left->left = NULL;
root->left->right = NULL;
}
void print()
{
Bst_node * ptr = get_inorder_predecessor(this->root);
if(ptr == NULL) std::cout<<"NULL\n";
else std::cout<<ptr->data<<std::endl;
}
};
int main()
{
BST obj;
obj.create();
obj.print();
return 0;
}
The above code is working fine but when i define 'get_inorder_predecessor()' function outside the class it gives error see the below code.
#include <iostream>
class BST {
private:
struct Bst_node
{
int data;
struct Bst_node* left;
struct Bst_node* right;
}*root;
static Bst_node* get_inorder_predecessor(Bst_node* ptr);
public:
void create()
{`
root = new Bst_node;
root->data = 8;
root->right = NULL;
root->left = new Bst_node;
root->left->data = 10;
root->left->left = NULL;
root->left->right = NULL;
}
void print()
{
Bst_node * ptr = get_inorder_predecessor(this->root);
if(ptr == NULL) std::cout<<"NULL\n";
else std::cout<<ptr->data<<std::endl;
}
};
static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr)
{
ptr = ptr->left;
if (ptr == NULL) return NULL;
while (ptr->right != NULL)
{
ptr = ptr->right;
}
return ptr;
}
int main()
{
BST obj;
obj.create();
obj.print();
return 0;
}
See the ERRORS:
'''binary.cpp:33:13: error: 'struct BST::Bst_node' is private within this context
static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr)
^~~~~~~~
binary.cpp:4:12: note: declared private here
struct Bst_node
^~~~~~~~
binary.cpp:33:47: error: 'Bst_node' was not declared in this scope
static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr)
^~~~~~~~
binary.cpp:33:57: error: 'ptr' was not declared in this scope
static BST::Bst_node* get_inorder_predecessor(Bst_node* ptr)
^~~
'''

WL_SHM_FORMAT_ARGB8888 not fully transparent if color bit was set

I am learning Wayland client programming and now I'm trying to make transparent surface.
I created a buffer and paint each pixels to shared memory. I am using WL_SHM_FORMAT_ARGB8888 format but it is not working as I expected.
As I understand, 0x00ff0000 means 255 red, 0 green, 0 blue and 0 alpha so the pixel should not shown. But it shows semi-transparent red surface to me.
Below is entire source code working on Weston compositor.
// main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>
#include "xdg-shell.h"
struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct wl_surface *surface;
struct zxdg_shell_v6 *xdg_shell = NULL;
struct zxdg_surface_v6 *xdg_surface;
struct zxdg_toplevel_v6 *xdg_toplevel;
struct wl_shm *shm;
struct wl_buffer *buffer;
void *shm_data;
int WIDTH = 480;
int HEIGHT = 360;
//===============
// Xdg
//===============
static void xdg_shell_ping_handler(void *data, struct zxdg_shell_v6 *xdg_shell,
uint32_t serial)
{
zxdg_shell_v6_pong(xdg_shell, serial);
printf("ping pong!\n");
}
static const struct zxdg_shell_v6_listener xdg_shell_listener = {
.ping = xdg_shell_ping_handler,
};
static void xdg_toplevel_configure_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height,
struct wl_array *states)
{
printf("Configure: %dx%d\n", width, height);
}
static void xdg_toplevel_close_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel)
{
printf("Close\n");
}
static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
.configure = xdg_toplevel_configure_handler,
.close = xdg_toplevel_close_handler,
};
static void xdg_surface_configure_handler(void *data,
struct zxdg_surface_v6 *xdg_surface, uint32_t serial)
{
fprintf(stderr, "xdg_surface_configure_handler().\n");
zxdg_surface_v6_ack_configure(xdg_surface, serial);
}
static const struct zxdg_surface_v6_listener xdg_surface_listener = {
.configure = xdg_surface_configure_handler,
};
//=================
// File system
//=================
static int set_cloexec_or_close(int fd)
{
long flags;
if (fd == -1) {
return -1;
}
flags = fcntl(fd, F_GETFD);
if (flags == -1)
goto err;
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
goto err;
return fd;
err:
close(fd);
return -1;
}
static int create_tmpfile_cloexec(char *tmpname)
{
int fd;
#ifdef HAVE_MKOSTEMP
fd= mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0) {
unlink(tmpname);
}
#else
fd = mkstemp(tmpname);
if (fd >= 0) {
fd = set_cloexec_or_close(fd);
unlink(tmpname);
}
#endif
return fd;
}
int os_create_anonymous_file(off_t size)
{
static const char template[] = "/blusher-shared-XXXXXX";
const char *path;
char *name;
int fd;
path = getenv("XDG_RUNTIME_DIR");
if (!path) {
errno = ENOENT;
return -1;
}
name = malloc(strlen(path) + sizeof(template));
if (!name) {
return -1;
}
strcpy(name, path);
strcat(name, template);
fd = create_tmpfile_cloexec(name);
free(name);
if (fd < 0) {
return -1;
}
if (ftruncate(fd, size) < 0) {
close(fd);
return -1;
}
return fd;
}
//==============
// Painting
//==============
static void paint_pixels()
{
uint32_t *pixel = shm_data;
fprintf(stderr, "Painting pixels.\n");
for (int n = 0; n < WIDTH * HEIGHT; ++n) {
if (n > 1100 && n < 1200) {
pixel[n] = 0xffff0000; // please ignore this
} else {
pixel[n] = 0x00ff0000;
}
}
}
static struct wl_buffer* create_buffer()
{
struct wl_shm_pool *pool;
int stride = WIDTH * 4; // 4 bytes per pixel
int size = stride * HEIGHT;
int fd;
struct wl_buffer *buff;
fd = os_create_anonymous_file(size);
if (fd < 0) {
fprintf(stderr, "Creating a buffer file for %d B filed: %m\n",
size);
exit(1);
}
shm_data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED) {
fprintf(stderr, "mmap filed: %m\n");
close(fd);
exit(1);
}
pool = wl_shm_create_pool(shm, fd, size);
buff = wl_shm_pool_create_buffer(
pool,
0,
WIDTH,
HEIGHT,
stride,
WL_SHM_FORMAT_ARGB8888
);
wl_shm_pool_destroy(pool);
return buff;
}
static void create_window()
{
buffer = create_buffer();
wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_damage(surface, 0, 0, WIDTH, HEIGHT);
wl_surface_commit(surface);
}
static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
// struct display *d = data;
// d->formats |= (1 << format);
fprintf(stderr, "Format %d\n", format);
}
struct wl_shm_listener shm_listener = {
shm_format,
};
//==============
// Global
//==============
static void global_registry_handler(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
if (strcmp(interface, "wl_compositor") == 0) {
fprintf(stderr, "Interface is <wl_compositor>.\n");
compositor = wl_registry_bind(
registry,
id,
&wl_compositor_interface,
version
);
} else if (strcmp(interface, "zxdg_shell_v6") == 0) {
fprintf(stderr, "Interface is <zxdg_shell_v6>.\n");
xdg_shell = wl_registry_bind(registry, id, &zxdg_shell_v6_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
fprintf(stderr, "Interface is <wl_shm>.\n");
shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
wl_shm_add_listener(shm, &shm_listener, NULL);
} else {
// printf("(%d) Got a registry event for <%s> id <%d>\n",
// version, interface, id);
}
}
static void global_registry_remover(void *data, struct wl_registry *registry,
uint32_t id)
{
printf("Got a registry losing event for <%d>\n", id);
}
static const struct wl_registry_listener registry_listener = {
global_registry_handler,
global_registry_remover
};
//==============
// Main
//==============
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "Can't connect to display.\n");
exit(1);
}
printf("Connected to display.\n");
struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, NULL);
wl_display_dispatch(display);
// wl_display_roundtrip(display);
// Check compositor.
fprintf(stderr, " - Checking compositor...\n");
if (compositor == NULL) {
fprintf(stderr, "Can't find compositor.\n");
exit(1);
}
// Check surface.
fprintf(stderr, " - Checking surface...\n");
surface = wl_compositor_create_surface(compositor);
if (surface == NULL) {
fprintf(stderr, "Can't create surface.\n");
exit(1);
}
if (xdg_shell == NULL) {
fprintf(stderr, "Haven't got a Xdg shell.\n");
exit(1);
}
zxdg_shell_v6_add_listener(xdg_shell, &xdg_shell_listener, NULL);
// Check shell surface.
xdg_surface =
zxdg_shell_v6_get_xdg_surface(xdg_shell, surface);
zxdg_surface_v6_add_listener(xdg_surface, &xdg_surface_listener, NULL);
xdg_toplevel = zxdg_surface_v6_get_toplevel(xdg_surface);
zxdg_toplevel_v6_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL);
// Signal that the surface is ready to be configured.
wl_surface_commit(surface);
// Wait for the surface to be configured.
wl_display_roundtrip(display);
create_window();
paint_pixels();
// wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_commit(surface);
while (wl_display_dispatch(display) != -1) {
;
}
wl_display_disconnect(display);
printf("Disconnected from display.\n");
return 0;
}
# Makefile
default:
wayland-scanner client-header /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.c
gcc -lwayland-client -lwayland-egl -lEGL -lGLESv2 main.c xdg-shell.c
But when I set pixel to 0x00000000, then it is fully transparent.
And in some tests, subsurfaces are completely transparent even there are color bits set. I want to know what is prevent the transparent toplevel surface with color bits.
If your wayland compositor supports alpha-compositing-v1 protocol you can use it do what you want.
In short; get a reference to zwp_alpha_compositing_v1 struct in you registry handler then after creating your surface you set it like this:
struct zwp_blending_v1* blending = zwp_alpha_compositing_v1_get_blending(<YOUR_ZWP_ALPHA_COMPOSITING>, <YOUR_WL_SURFACE>);
zwp_blending_v1_set_blending(blending, ZWP_BLENDING_V1_BLENDING_EQUATION_STRAIGHT);
This is an equivalent to (src_alpha, one_minus_src_alpha) blending.

How to get drag and drop events in GraphicsItem which is placed in GraphicsScene?

I have graphicsview(attached graphicscene)setted as a centralwidget in scene i added 2 rect items(graphicsItem) (both are draggable). when i drag 1 rect item when its scene it gets drag enter event but when enters to other rect item its not getting drag enter event. How to resolve this?
Below is working example.
graphicsview.h
class GraphicsView : public QGraphicsView
{
public:
GraphicsView();
};
graphicsview.cpp
GraphicsView::GraphicsView()
{
//setAcceptDrops(true);
}
graphicsScene.h
class GraphicsScene : public QGraphicsScene
{
public:
GraphicsScene();
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
};
graphicsScene.cpp
GraphicsScene::GraphicsScene()
{
}
void GraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
qDebug() << "Scene::dragEnterEvent";
event->acceptProposedAction();
}
void GraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
qDebug() << "Scene::dragMoveEvent";
event->acceptProposedAction();
}
void GraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
qDebug() << "Scene::dropEvent";
event->acceptProposedAction();
}
graphicsRectItem.h
class GraphicsRectItem : public QGraphicsRectItem
{
public:
GraphicsRectItem();
static QString MimeType() { return QStringLiteral("job/x-job"); }
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
};
graphicsRectItem.cpp
GraphicsRectItem::GraphicsRectItem()
{
setAcceptDrops(true);
}
void GraphicsRectItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "RectItem::mousePressEvent";
setCursor(Qt::ClosedHandCursor);
}
void GraphicsRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "RectItem::mouseMoveEvent";
if (QLineF(event->screenPos(), event-
>buttonDownScreenPos(Qt::LeftButton))
.length() < QApplication::startDragDistance()) {
QGraphicsRectItem::mouseMoveEvent(event);
return;
}
qDebug() << "drag before executed";
QByteArray itemData;
QString m_jobName = "rect";
DataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << m_jobName ;
QMimeData *mimeData = new QMimeData;
mimeData->setData(GraphicsRectItem::MimeType(), itemData);
QDrag *drag = new QDrag(event->widget());
drag->setMimeData(mimeData);
drag->exec();
qDebug() << "drag executed";
setCursor(Qt::OpenHandCursor);
}
void GraphicsRectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "RectItem::mouseReleaseEvent";
setCursor(Qt::OpenHandCursor);
}
void GraphicsRectItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
qDebug() << "RectItem::dragEnterEvent";
event->acceptProposedAction();
}
void GraphicsRectItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
qDebug() << "RectItem::dragMoveEvent";
event->acceptProposedAction();
}
void GraphicsRectItem::dropEvent(QGraphicsSceneDragDropEvent *event)
{
qDebug() << "RectItem::dropEvent";
event->acceptProposedAction();
}
Mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pView = new GraphicsView;
m_pScene = new GraphicsScene;
m_pView->setScene(m_pScene);
GraphicsRectItem *rect1 = new GraphicsRectItem;
rect1->setRect(10,10,55,55);
GraphicsRectItem *rect2 = new GraphicsRectItem;
rect2->setRect(75,10,55,55);
m_pScene->addItem(rect1);
m_pScene->addItem(rect2);
this->setCentralWidget(m_pView);
}
MainWindow::~MainWindow()
{
delete ui;
}

C++ class member variable resetting to 0

I'm trying to increment and decrement the index of a list of readings, however, everytime I run update(), m_notifIndex gets set back to zero. I'm sorry if this type of question has been asked before, but after looking for the answer for an hour, I gave up and went on to ask my first question here. Sorry for the bad formatting too, again, this is my first time posting.
Display.cpp
#include "display.h"
#include <time.h>
#include <unistd.h>
#include <iostream>
Display::Display(unsigned int width, unsigned int height, unsigned int num_sensors, std::string* sensors, const std::string& dir, Message* messages) {
m_notifIndex = 0;
}
void Display::update() {
if (m_showNotif) {
//when there are no more messages, show the notifications
while (!m_notifications->isEmpty()) {
//first draw the notification if there is a warning in the current index
if (m_notifications->sensors[m_notifIndex] != NULL) {
m_oled->clear(PAGE);
drawSensor();
m_oled->display();
sleep(1);
//keep updating the message and notif stack when there are no inputs
while (m_a->pinRead() == HIGH && m_right->pinRead() == HIGH && m_left->pinRead() == HIGH && m_b->pinRead() == HIGH) {
m_messages->updateMsgStack();
updateNotif();
if (!m_messages->isEmpty() || m_notifications->warnings[m_notifIndex])
return; //break away from the loop if a new message comes in
}
//listen in for inputs
if (m_right->pinRead() == LOW) {
//wait until the button is released
while (m_right->pinRead() == LOW) {}
if (m_notifIndex == m_num_sensors-1)
m_notifIndex = 0; //wrap around when at the end
else m_notifIndex++;
}
else if (m_left->pinRead() == LOW) {
while (m_left->pinRead() == LOW) {}
if (m_notifIndex == 0)
m_notifIndex = m_num_sensors-1; //wrap around when at the beginning
else m_notifIndex--;
}
else if (m_a->pinRead() == LOW) {
while (m_a->pinRead() == LOW) {}
m_showNotif = false;
return;
}
checkForPanic();
}
else { //when the current index has no warning
if (m_notifIndex == m_num_sensors-1)
m_notifIndex = 0; //wrap around when at the end
else m_notifIndex++;
}
}
}
}
void Display::updateNotif() {
std::string line;
for (unsigned int i = 0; i < sizeof(m_sensors)/sizeof(m_sensors[0]); i++) {
const char* filePath = (m_notifDir + m_sensors[i] + ".txt").c_str();
if (m_messages->exists(filePath)) {
usleep(10000);
try {
m_messages->m_incMsg.open(filePath);
while(std::getline(m_messages->m_incMsg, line)) {
m_notifications->addWarning (line, i);
}
m_messages->m_incMsg.close();
}
catch (std::ios_base::failure& e) {
std::cerr << e.what() << '\n' << std::endl;
}
}
else m_notifications->removeWarning (i); //delete the warning when the file doesnt exist
}
}
void Display::checkForPanic() {
if (m_b->pinRead() == LOW) {
time_t hold;
time(&hold);
while (m_b->pinRead() == LOW) {
if (time(NULL) > hold + 3) { //if the timer reaches 3 seconds
//m_messages->sendReply("Miner_Emergency");
return;
}
}
}
}
Display.h
#ifndef OLED_DISPLAY_H_
#define OLED_DISPLAY_H_
#include <sstream>
#include <string>
#include "image/image.h"
#include "oled/Edison_OLED.h"
#include "message.h"
#include "DataStructs/Notif.h"
#include "gpio/gpio.h"
#define SLEEPTIMEOUT 20
class Display {
public:
Display(unsigned int width, unsigned int height, unsigned int num_sensors, std::string* sensors, const std::string& dir, Message* messages);
void run();
~Display();
private:
edOLED* m_oled;
const unsigned int m_height, m_width;
Image* m_miner;
Image* m_checkin;
Image* m_reminder;
Image* m_blast;
Image* m_go_to;
Image* m_goto_zone;
bool m_isSleeping, m_showNotif;
time_t m_timer;
Message* m_messages;
std::string* m_sensors;
std::string m_notifDir;
NotifHandler* m_notifications;
unsigned int m_notifIndex;
const unsigned int m_num_sensors;
gpio* m_up;
gpio* m_down;
gpio* m_left;
gpio* m_right;
gpio* m_a;
gpio* m_b;
void drawImage(Image* image);
void update();
void drawMessage(MsgNode* message);
void drawTime();
void drawSensor();
void updateNotif();
void checkForPanic();
};
#endif //OLED_DISPLAY_H_

mutex and condition variable implementation using futex

I have implemented mutex and contition variables using futex syscall. I believe that my implementation is correct, but would like it to be verified by some one else. If some of you could verify its correctness, it would be a great help.
Any suggestions for further improvements in the performance of the mutex and contition variables would also be appreciated.
#ifndef __SYNCHRONIZATION__
#define __SYNCHRONIZATION__
#include <unistd.h>
#include <limits.h>
#include <sys/syscall.h>
#include <linux/futex.h>
#include "types.h"
#include "assembly.h"
typedef UINT32 mutex;
typedef struct condvar condvar;
struct condvar {
mutex *m;
int seq;
};
void mutex_init(mutex *m) {
*m = 0;
}
void mutex_destroy(mutex *m) {
*m = 0;
}
void mutex_lock(mutex *m) {
UINT32 c;
if((c = __sync_val_compare_and_swap(m, 0, 1)) != 0) {
do {
if((c == 2) || __sync_val_compare_and_swap(m, 1, 2) != 0)
syscall(SYS_futex, m, FUTEX_WAIT_PRIVATE, 2, NULL, NULL, 0);
} while((c = __sync_val_compare_and_swap(m, 0, 2)) != 0);
}
}
void mutex_unlock(mutex *m) {
if(__sync_fetch_and_sub(m, 1) != 1) {
*m = 0;
syscall(SYS_futex, m, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
}
}
void cond_init(condvar *c, mutex *m) {
c->m = m;
c->seq = 0;
}
void cond_destroy(condvar *c) {
c->m = NULL;
c->seq = 0;
}
void cond_signal(condvar *c) {
__sync_fetch_and_add(&(c->seq), 1);
syscall(SYS_futex, &(c->seq), FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
}
void cond_broadcast(condvar *c) {
__sync_fetch_and_add(&(c->seq), 1);
syscall(SYS_futex, &(c->seq), FUTEX_REQUEUE_PRIVATE, 1, (void *) INT_MAX, c->m, 0);
}
void cond_wait(condvar *c) {
UINT32 oldSeq = c->seq;
mutex_unlock(c->m);
syscall(SYS_futex, &(c->seq), FUTEX_WAIT_PRIVATE, oldSeq, NULL, NULL, 0);
while (xchg32(c->m, 2)) {
syscall(SYS_futex, c->m, FUTEX_WAIT_PRIVATE, 2, NULL, NULL, 0);
}
}
#endif
Thanks
Sudhanshu