Connecting SLOTS in Qt - c++

I have a context menu and edit menu. I want to connect context menu slots with the edit menu.
Like EDIT menu has menu Items: cut, copy and paste
My context menu slots are:
void CadGraphicsScene::cut(getEntity *obj)
{
// id of item pasted is kept same as that of the item being cut
removeItem(obj);
clipboardStack::instance()->push(obj->clone(contextItemId));
}
void CadGraphicsScene::copy(getEntity *obj)
{
// id of item pasted is one more than total number of items in the scene
clipboardStack::instance()->push(obj->clone(++id));
}
void CadGraphicsScene::paste(const QPointF &pos)
{
// gets the items cut/copy from clipboardStack to paste
getEntity *pasteEntity = clipboardStack::instance()->pop();
if (pasteEntity->type() == Point::Type)
{
Point *itemPtr = dynamic_cast<Point *>(pasteEntity);
itemPtr->position = pos;
drawEntity(itemPtr);
}
if (pasteEntity->type() == Line::Type)
{
Line *itemPtr = dynamic_cast<Line *>(pasteEntity);
itemPtr->startP = pos;
/* calculates difference between startP of line being cut/copy and line
* being pasted for proper pasting of line
*/
differenceX = itemPtr->startP.x() - lineStartPoint.x();
differenceY = itemPtr->startP.y() - lineStartPoint.y();
itemPtr->endP = QPointF(lineEndPoint.x() + differenceX,
lineEndPoint.y() + differenceY);
drawEntity(itemPtr);
}
if (pasteEntity->type() == Circle::Type)
{
Circle *itemPtr = dynamic_cast<Circle *>(pasteEntity);
itemPtr->centerP = pos;
drawEntity(itemPtr);
}
if (pasteEntity->type() == Ellipse::Type)
{
Ellipse *itemPtr = dynamic_cast<Ellipse *>(pasteEntity);
itemPtr->p1 = pos;
drawEntity(itemPtr);
}
if (pasteEntity->type() == Text::Type)
{
Text *itemPtr = dynamic_cast<Text *>(pasteEntity);
itemPtr->position = pos;
drawEntity(itemPtr);
}
setMode(NoMode);
}
//context menu actions
void CadGraphicsScene::menuAction(QAction *action)
{
if (action == cutAction)
{
cut(static_cast<getEntity *>(contextItem));
}
else if (action == copyAction)
{
copy(static_cast<getEntity *>(contextItem));
}
else if (action == pasteAction)
{
paste(contextPosition);
}
}
How can the same be done from edit menu? How can the same slots be used?
for cut in the edit menu I made another slot:
void CadgraphicsScene::cut()
{
cutAction
}
connect(actionCut, SIGNAL(triggered), this, SLOT(cut()));

If you want to reuse the same slots in your application's Edit menu, just use existing cutAction, copyAction and pasteAction actions when constructing it. So if you has established the connections for that actions the same slots will be called both when user triggers actions from context menu and from Edit menu.

Related

Processing2 selectInput() P3D clash

I've been studying this thread
Processing 2.0 - Open file dialog
with regard to the use of selectinput().
I'm hoping to import point data to construct some 3d plots.
I can import the data and construct the plot ok but when trying to use
selectinput() to choose a file I run into trouble.
The difficulty I am having is that selectinput() appears to be incompatible with a P3D
window.
Using OS X10.10
for example This code works
void setup() {
size(400, 400,P3D); //3Dgraphics specified
background(0);
stroke(255);
frameRate(20);
}
void draw() {
noFill();
ellipse(mouseX, mouseY, 90, 90);
and this works
String [] myInputFileContents ;
String myFilePath;
void setup() {
selectInput("Select a file : ", "fileSelected");
while (myInputFileContents == null) {//wait
// println("wait"); //If there is nothing inside the curly brackets
//delay(3000); //this doesn't work
size(400, 400 );/// If P3D is added it won't work
background(0);
//smooth();
stroke(255);
frameRate(25);
}
}
void draw() {
box(mouseX, mouseY, 150);
println("Selected at this point " + myFilePath);
}
void mousePressed() {
selectInput("Select a file : ", "fileSelected");
}
void fileSelected(File selection) {
if (selection == null) {
println("no selection so far...");
}
else {
myFilePath = selection.getAbsolutePath();
myInputFileContents = loadStrings(myFilePath) ;// this moves here...
println("User selected " + myFilePath);
}
}
but if
size(400, 400);
is changed to
size(400,400,P3D);
The frame displays but it won't draw.
Could someone point me to the answer?
It seems that this problem is some kind of frame loading problem. This "hackish" approached worked for me under OS X 10.10 Yoesemite. It should also work under windows. Oh and whenever you use selectInput() please use mouseReleased so the function only gets called once :)
Setup() gets called twice for whatever reason, this is why we have the didPreSelect boolean.
You call mousePressed instead of mouseReleased
The loop already had the screen selection in it, this is why i changed the loop.
The delay also has problems, this is why i added the delay inside the while-loop.
Man that was quite the challenge, +1 for asking.
PS: I added an exit() if you press cancel the first time you open the application, which should be more convenient.
String [] myInputFileContents ;
String myFilePath;
boolean didPreSelect = false;
boolean secondPress = false;
void setup() {
if (didPreSelect == false)
{
didPreSelect = true;
selectInput("Select a file : ", "fileSelected");
}
//frame = null;
while (myInputFileContents == null || myInputFileContents.length < 2) {//wait
delay(1000);
}
//this doesn't work
size(400, 400, P3D);
background(0);
//smooth();
stroke(255);
frameRate(25);
}
void draw() {
box(mouseX, mouseY, 150);
//println("Selected at this point " + myFilePath);
}
void mouseReleased() {
if(secondPress == false) secondPress = true;
selectInput("Select a file : ", "fileSelected");
}
void fileSelected(File selection) {
if (frameCount < 50)
{
if (selection == null) {
println("no selection so far...");
if(secondPress == false) exit();
} else {
myFilePath = selection.getAbsolutePath();
myInputFileContents = loadStrings(myFilePath) ;// this moves here..
println("User selected " + myFilePath);
}
}
}

How to Enable/Disable Menu Item 2 in OnUpdate Handler of Menu Item 1?

I have two menu items. When item 1 is disabled, I want item 2 to be disabled as well. In the OnUpdate handler of menu item 1, I have tried to use "t_pMenu = pCmdUI->m_pMenu;", "t_pMenu = pCmdUI->m_pSubMenu;" and "t_pMenu = pCmdUI->m_pParentMenu;" but I always get NULL t_pMenu. How can I achieve this purpose?
void CDummyView::OnUpdateMenuItem1(CCmdUI* pCmdUI)
{
if(m_bShowMenuItem1)
{
pCmdUI->SetText("Hide Features")
CMenu * t_pMenu = pCmdUI->m_pSubMenu;
if(t_pMenu != NULL)
t_pMenu->EnableMenuItem(ID_MENU_ITEM2, MF_ENABLED);
}
else
{
pCmdUI->SetText("Show Features")
CMenu * t_pMenu = pCmdUI->m_pParentMenu;
if(t_pMenu != NULL)
t_pMenu->EnableMenuItem(ID_MENU_ITEM2, MF_GRAYED);
}
}
void CDummyView::OnUpdateMenuItem2(CCmdUI* pCmdUI)
{
...
}
Never handle to different command IDs in one handler.
Each handler is called more than once if there are buttons and menu items. Also you don't know the sequence. When you alter the item2 in Item1 handler it may be enabled again when the handler for Item2 is called later.
When you have a flag named m_bShowMenuItem1 just use it.
void CDummyView::OnUpdateMenuItem1(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bShowMenuItem1);
}
void CDummyView::OnUpdateMenuItem2(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bShowMenuItem1);
}
I got it work. Below is the code I tried. Two flag variables m_bShowFeatures and m_bShowSmallFetures are initialized to be TRUE.
void CDummyView::OnMenuItem1()
{
m_bShowFeatures = !m_bShowFeatures;
m_pDoc->UpdateAllViews(NULL, SHOW_HIDE_ALL_FEATURES);
}
void CDummyView::OnUpdateMenuItem1(CCmdUI* pCmdUI)
{
if(m_bShowFeatures)
pCmdUI->SetText("Hide Features")
else
pCmdUI->SetText("Show Features")
}
void CDummyView::OnMenuItem2()
{
m_bShowSmallFetures= !m_bShowSmallFetures;
m_pDoc->UpdateAllViews(NULL, SHOW_HIDE_SMALL_FEATURES);
}
void CDummyView::OnUpdateMenuItem2(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bShowFetures)
if(m_bShowSmallFetures)
pCmdUI->SetText("Hide Small Features")
else
pCmdUI->SetText("Show Small Features")
}
So OnUpdateMenuItem2() does get invoked after OnMenuItem1() is called when Menu Item 1 is clicked. I didn't expect that.

How to disable middle button functionality of QTextEdit?

I don't want mouse middle button to paste text in my QTextEdit. This code doesn't work. TextEdit inherits QTextEdit. After mouse middle button pastes it pastes copied text.
void TextEdit::mousePressEvent ( QMouseEvent * e ) {
if (e->button() == Qt::MidButton) {
e->accept();
return;
};
QTextEdit::mousePressEvent(e);
}
As mouse clicks are usually registered when the button is released, you should redefine the mouseReleaseEvent function.
You don't even need to redefine mousePressEvent, because the middle button isn't handled at all by that function.
I'm assuming you're using Linux here; right clicking in the window is likely to be triggering an insertion of mime data before you get to handle the mouse event, which is why it is still pasting text.
Therefore, according to Qt docs for paste: - " to modify what QTextEdit can paste and how it is being pasted, reimplement the virtual canInsertFromMimeData() and insertFromMimeData() functions."
I've been in the same case, that is to say: having parts of my CustomQTextEdit required to be non-editable.
As I truly love the middle mouse button paste feature, I did not wanted to disable it. So, here is the (more or less quick and dirty coded) workaround I used:
void QTextEditHighlighter::mouseReleaseEvent(QMouseEvent *e)
{
QString prev_text;
if (e->button() == Qt::MidButton) {
// Backup the text as it is before middle button click
prev_text = this->toPlainText();
// And let the paste operation occure...
// e->accept();
// return;
}
// !!!!
QTextEdit::mouseReleaseEvent(e);
// !!!!
if (e->button() == Qt::MidButton) {
/*
* Keep track of the editbale ranges (up to you).
* My way is a single one range inbetween the unique
* tags "//# BEGIN_EDIT" and "//# END_EDIT"...
*/
QRegExp begin_regexp = QRegExp("(^|\n)(\\s)*//# BEGIN_EDIT[^\n]*(?=\n|$)");
QRegExp end_regexp = QRegExp("(^|\n)(\\s)*//# END_EDIT[^\n]*(?=\n|$)");
QTextCursor from = QTextCursor(this->document());
from.movePosition(QTextCursor::Start);
QTextCursor cursor_begin = this->document()->find(begin_regexp, from);
QTextCursor cursor_end = this->document()->find(end_regexp, from);
cursor_begin.movePosition(QTextCursor::EndOfBlock);
cursor_end.movePosition(QTextCursor::StartOfBlock);
int begin_pos = cursor_begin.position();
int end_pos = cursor_end.position();
if (!(cursor_begin.isNull() || cursor_end.isNull())) {
// Deduce the insertion index by finding the position
// of the first character that changed between previous
// text and the current "after-paste" text
int insert_pos; //, end_insert_pos;
std::string s_cur = this->toPlainText().toStdString();
std::string s_prev = prev_text.toStdString();
int i_max = std::min(s_cur.length(), s_prev.length());
for (insert_pos=0; insert_pos < i_max; insert_pos++) {
if (s_cur[insert_pos] != s_prev[insert_pos])
break;
}
// If the insertion point is not in my editable area: just restore the
// text as it was before the paste occured
if (insert_pos < begin_pos+1 || insert_pos > end_pos) {
// Restore text (ghostly)
((MainWindow *)this->topLevelWidget())->disconnect(this, SIGNAL(textChanged()), ((MainWindow *)this->topLevelWidget()), SLOT(on_textEdit_CustomMacro_textChanged()));
this->setText(prev_text);
((MainWindow *)this->topLevelWidget())->connect(this, SIGNAL(textChanged()), ((MainWindow *)this->topLevelWidget()), SLOT(on_textEdit_CustomMacro_textChanged()));
}
}
}
}

OOP Game Menu System Development Conceptualising

I'm trying to write an OO menu system for a game, loosely based on the idea of a Model,View,Controller. In my app so far I've named the views "renderers" and the models are without a suffix. I created a generic menu class which stores the items of a menu, which are menu_item objects, and there is also a menu renderer class which creates renderers for each item and renders them. The problem is I'm not sure where to store the data and logic to do with where on the screen each item should be positioned, and how to check if it is being hovered over, etc. My original idea was to store and set a selected property on each menu item, which could be rendered differently by different views, but even then how to I deal with positioning the graphical elements that make up the button?
Code excerpts so far follow: (more code at https://gist.github.com/3422226)
/**
* Abstract menu model
*
* Menus have many items and have properties such as a title
*/
class menu {
protected:
std::string _title;
std::vector<menu_item*> _items;
public:
std::string get_title();
void set_title(std::string);
std::vector<menu_item*> get_items();
};
class menu_controller: public controller {
private:
menu* _menu;
public:
menu_controller(menu*);
virtual void update();
};
class menu_item {
protected:
std::string _title;
public:
menu_item(std::string title);
virtual ~menu_item();
std::string get_title();
};
class menu_renderer: public renderer {
private:
menu* _menu;
bitmap _background_bitmap;
static font _title_font;
std::map<menu_item*, menu_item_renderer*> _item_renderers;
public:
menu_renderer(menu*);
virtual void render();
};
font menu_renderer::_title_font = NULL;
menu_renderer::menu_renderer(menu* menu) {
_menu = menu;
_background_bitmap = ::load_bitmap("blackjack_menu_bg.jpg");
if (!_title_font)
_title_font = ::load_font("maven_pro_regular.ttf",48);
}
void menu_renderer::render() {
::draw_bitmap(_background_bitmap, 0, 0);
/* Draw the menu title */
const char* title = _menu->get_title().c_str();
int title_width = ::text_width(_title_font, title);
::draw_text(title, color_white, _title_font, screen_width() - title_width - 20, 20);
/* Render each menu item */
std::vector<menu_item*> items = _menu->get_items();
for (std::vector<menu_item*>::iterator it = items.begin(); it != items.end(); ++it) {
menu_item* item = *it;
if (!_item_renderers.count(item))
_item_renderers[item] = new menu_item_renderer(item, it - items.begin());
_item_renderers[item]->render();
}
}
class menu_item_renderer: public renderer {
private:
unsigned _order;
menu_item* _item;
static font _title_font;
public:
menu_item_renderer(menu_item*, unsigned);
virtual ~menu_item_renderer();
virtual void render();
};
font menu_item_renderer::_title_font = NULL;
menu_item_renderer::menu_item_renderer(menu_item* item, unsigned order) {
_item = item;
_order = order;
if (!_title_font)
_title_font = ::load_font("maven_pro_regular.ttf",24);
}
menu_item_renderer::~menu_item_renderer() {
// TODO Auto-generated destructor stub
}
void menu_item_renderer::render() {
const char* title = _item->get_title().c_str();
int title_width = ::text_width(_title_font, title);
unsigned y = 44 * _order + 20;
::fill_rectangle(color_red, 20, y, title_width + 40, 34);
::draw_text(title, color_white, _title_font, 30, y + 5);
}
Your Model class menu needs a add_view(menuview *v) and update() method.
Then you can delegate the update of your widget to the derived View (menu_renderer or a cli_menu_renderer).
The Controller needs to know the Model (as member), when the Controller runs (or executes a Command) and has to update the Model with a Setter (like m_menu_model->set_selected(item, state)) and the Model calls update() on Setters.
Your Controller menu_controller has a update method, there you could also ask for Input, like if (menuview->toggle_select()) m_menu_model->toggle_selected(); (which all menuviews have to implement) and invoke the setter, but thats a inflexible coupling of View and Controller (you could check MVC with the Command Pattern for a more advanced combination).
For the Position you can set member vars like int m_x, m_y, m_w, m_h.
But these members are specific to a View with GUI, so only the derived View needs them.
Then you could use these values to compare against mouse Positions and use a MouseOver Detection Method like this:
// View menu_item
bool menu_item::over()
{
if (::mouse_x > m_x
&& ::mouse_x < m_x + m_w
&& ::mouse_y > m_y
&& ::mouse_y < m_y + m_h) {
return true;
}
return false;
}
// update on gui menu item
bool menu_item::update()
{
if (over()) {
m_over = true;
}
else {
m_over = false;
}
// onclick for the idea
if ((::mouse_b & 1) && m_over) {
// here you could invoke a callback or fire event
m_selected = 1;
} else {
m_selected = 0;
}
return m_selected;
}
// update the command line interface menu item
bool cli_menu_item::update()
{
if ((::enterKeyPressed & 1) && m_selected) {
// here you could invoke a callback or fire event
m_selected = 1;
} else {
m_selected = 0;
}
return m_selected;
}
void menu_item_renderer::render() {
// update widgets
_item->update();
// ...
}
// Model
void menu::add_view(menuview *v) {
m_view=v;
}
void menu::update() {
if (m_view) m_view->update();
}
bool menu::set_selected(int item, int state) {
m_item[index]=state;
update();
}

Adding Row Specific context menu to an UltraWinGrid

I'm a newbie using Infragistics. I'm trying to add context menu to a specific row/column in UltraWinGrid, which I'm not able to. Looks like adding context menu to the grid is simple but adding it to a specific row/column is not straight forward. Can you please tell me how to do this?
You could add a context menu to the form or control your grid will reside in and only display it in when they right click in the grid over the rows/cells that need that menu.
Here's an example, though it's not pretty.
private void UltraGrid_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
ContextMenu.Hide();
Point point = new System.Drawing.Point(e.X, e.Y);
UIElement uiElement = ((UltraGridBase) sender).DisplayLayout.UIElement.ElementFromPoint(point);
UltraGridCell cell = (UltraGridCell) uiElement.GetContext(typeof (UltraGridCell));
if (cell != null && UseThisContextMenu(cell))
{
ContextMenu.Show();
}
}
}
MouseDown does not work. Please use MouseUp.
private void UltraGrid1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Point point = new System.Drawing.Point(e.X, e.Y);
UIElement uiElement = ((UltraGridBase)sender).DisplayLayout.UIElement.ElementFromPoint(point);
UltraGridCell cell = (UltraGridCell)uiElement.GetContext(typeof(UltraGridCell));
if (cell.Band.Index == 0)
{
if (cell.Column.Key.Equals("ColumnToShow"))
{
contextMenuStrip.Show();
}
else
{
contextMenuStrip.Hide();
}
}
}
}
}