1 /*
2 	Copyright (C) 2010 Andres Cabrera
3 	mantaraya36@gmail.com
4 
5 	This file is part of CsoundQt.
6 
7 	CsoundQt is free software; you can redistribute it
8 	and/or modify it under the terms of the GNU Lesser General Public
9 	License as published by the Free Software Foundation; either
10 	version 2.1 of the License, or (at your option) any later version.
11 
12 	CsoundQt is distributed in the hope that it will be useful,
13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 	GNU Lesser General Public License for more details.
16 
17 	You should have received a copy of the GNU Lesser General Public
18 	License along with Csound; if not, write to the Free Software
19 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 	02111-1307 USA
21 */
22 
23 #ifndef WIDGETLAYOUT_H
24 #define WIDGETLAYOUT_H
25 
26 #include <QtGui>
27 
28 #define QCS_MAX_EVENTS 4096
29 #define QCS_CURVE_BUFFER_MAX 4096
30 
31 #include "qutewidget.h"
32 #include "curve.h"
33 #include "widgetpreset.h"
34 
35 class QuteConsole;
36 class QuteGraph;
37 class QuteScope;
38 class QuteButton;
39 class FrameWidget;
40 class QuteTable;
41 
42 class RegisteredController {
43 public:
RegisteredController(QuteWidget * _widget,int _chan,int _cc)44 	RegisteredController(QuteWidget * _widget, int _chan,int  _cc) {
45 		widget = _widget;
46 		chan = _chan;
47 		cc = _cc;
48 	}
49 	int chan;
50 	int cc;
51 	QuteWidget * widget;
52 };
53 
54 class WidgetLayout : public QWidget
55 {
56 	Q_OBJECT
57 	Q_PROPERTY(bool openProperties READ getOpenProperties WRITE setOpenProperties) // To make sure only one properties dialog is displayed at any one time
58 public:
59 	WidgetLayout(QWidget* parent);
60 	~WidgetLayout();
61 	//    unsigned int widgetCount();
62 	//    void loadWidgets(QString widgets);
63 	void loadXmlWidgets(QString xmlWidgets);
64 	void loadXmlPresets(QString xmlPresets);
65 	void loadMacWidgets(QString macWidgets);
66 	QString getWidgetsText(); // With full tags
67 	QString getPresetsText();
68 	QString getSelectedWidgetsText();
69 	QString getMacWidgetsText(); // With full tags
70 	QStringList getSelectedMacWidgetsText();
71 	QString getCsladspaLines();
72 	QString getCabbageWidgets();
73 	bool openMidiPort(int port);
74 	void closeMidiPort();
getWidgets()75 	QVector<QuteWidget *> getWidgets() {return m_widgets;}
76 
77 	// Data to/from widgets
78 	void setValue(QString channelName, double value);
79 	void setValue(QString channelName, QString value);
80 	void setValue(int index, double value);
81 	void setValue(int index, QString value);
82 	QString getStringForChannel(QString channelName, bool *modified = 0);
83 	double getValueForChannel(QString channelName, bool *modified = 0);
84 	void getMouseValues(QVector<double> *values);
85 	int getMouseX();
86 	int getMouseY();
87 	int getMouseRelX();
88 	int getMouseRelY();
89 	int getMouseBut1();
90 	int getMouseBut2();
91 	void setWidgetProperty(QString widgetid, QString property, QVariant value);
92 	QVariant getWidgetProperty(QString widgetid, QString property);
93 	void flush();
94 
95 	// Behavior
96 	void setKeyRepeatMode(bool repeat);
97 	void showWidgetTooltips(bool show);
98 	void setWidgetToolTip(QuteWidget *widget, bool show);
99 	void setContained(bool contained);
100 	void setCurrentPosition(QPoint pos); // To set the mouse position for new widgets
101 	void setFontOffset(double offset);
102 	void setFontScaling(double scaling);
103 	void setWidgetsLocked(bool lock);
setUpdateRate(int rate)104     void setUpdateRate(int rate) { m_updateRate = rate; }
105 
106 	// Properties
getOpenProperties()107 	bool getOpenProperties() { return m_openProperties; }
setOpenProperties(bool open)108 	void setOpenProperties(bool open) {m_openProperties = open; }
109 	// Outer geometry refers to the geometry of the parent panel if not separate window
110 	void setOuterGeometry(QRect r);
111 	QRect getOuterGeometry();
112 
113 	//    void getValues(QVector<QString> *channelNames,
114 	//                   QVector<double> *values,
115 	//                   QVector<QString> *stringValues);
116 
117 	bool uuidFree(QString uuid);
118 	int newXmlWidget(QDomNode node, bool offset = false, bool newId = false);
119 	QString newMacWidget(QString widgetLine, bool offset = false);  // Offset is used when pasting duplicated widgets
120 	void registerWidget(QuteWidget *widget);
121 
122 	QVector<QVector<int> > midiQueue;
123 	int midiWriteCounter;
124 	int midiReadCounter;
125 
126 	// Notifiations
127 	void engineStopped(); // To let the widgets know engine has stopped (to free unused curve buffers)
128 
129 	// Preset methods
130 	void setPresetName(int num, QString name);
131 	QList<int> getPresetNums();
132 	QString getPresetName(int num);
133 	bool presetExists(int num);
134 
135 	// Curves from API
136 	void appendCurve(WINDAT *windat);
137 	void killCurve(WINDAT *windat);
138 	void newCurve(Curve* curve);
139 	void setCurveData(Curve *curve);
140 	uintptr_t getCurveById(uintptr_t id);
141 	void updateCurve(WINDAT *windat);
142 	int killCurves(CSOUND *csound);
143 	void clearGraphs(); // This also frees the memory allocated by curves.
144 	void flushGraphBuffer();
145 
146 	void refreshWidgets();
147 	bool isModified();
148 	//    void passWidgetClipboard(QString text);
149 
150 	void createContextMenu(QContextMenuEvent *event);  // When done outside container widget
151 
152 	// Edition Actions  (Local edit actions without keyboard shortcuts as the main application handles that)
153 	QAction *cutAct;
154 	QAction *copyAct;
155 	QAction *pasteAct;
156     QAction *reloadWidgetsAct;
157 	QAction *clearAct;
158 	QAction *selectAllAct;
159 	QAction *duplicateAct;
160 	QAction *deleteAct;
161 	QAction *propertiesAct;
162 
163 	// Create new widget Actions
164 	QAction *createSliderAct;
165 	QAction *createLabelAct;
166 	QAction *createDisplayAct;
167 	QAction *createScrollNumberAct;
168 	QAction *createLineEditAct;
169 	QAction *createSpinBoxAct;
170 	QAction *createButtonAct;
171 	QAction *createKnobAct;
172 	QAction *createCheckBoxAct;
173 	QAction *createMenuAct;
174 	QAction *createMeterAct;
175 	QAction *createConsoleAct;
176 	QAction *createGraphAct;
177 	QAction *createScopeAct;
178     QAction *createTableDisplayAct;
179 
180 	// Alignment Actions
181 	QAction *alignLeftAct;
182 	QAction *alignRightAct;
183 	QAction *alignTopAct;
184 	QAction *alignBottomAct;
185 	QAction *sendToBackAct;
186     QAction *sendToFrontAct;
187 	QAction *distributeHorizontalAct;
188 	QAction *distributeVerticalAct;
189 	QAction *alignCenterHorizontalAct;
190 	QAction *alignCenterVerticalAct;
191 
192 	// Preset actions
193 	QAction *storePresetAct;
194 	QAction *newPresetAct;
195 	QAction *recallPresetAct;
196 
197     // Value changes buffer to store all value changes from widgets that
198     // have been triggered from the GUI
199 	QHash<QString, double> newValues;
200 	QHash<QString, QString> newStringValues;
201 	QMutex valueMutex;
202 	QMutex stringValueMutex;
203 	QReadWriteLock mouseLock;
204 
205     QString getQml();
206 
207     QuteWidgetType widgetNameToType(QString widgetName);
208     void addCreateWidgetActionsToMenu(QMenu &menu);
209 
210 public slots:
211 	QString createNewLabel(int x = -1, int y = -1, QString channel = QString());
212 	QString createNewDisplay(int x = -1, int y = -1, QString channel = QString());
213 	QString createNewScrollNumber(int x = -1, int y = -1, QString channel = QString());
214 	QString createNewLineEdit(int x = -1, int y = -1, QString channel = QString());
215 	QString createNewSpinBox(int x = -1, int y = -1, QString channel = QString());
216 	QString createNewSlider(int x = -1, int y = -1, QString channel = QString());
217 	QString createNewButton(int x = -1, int y = -1, QString channel = QString());
218 	QString createNewKnob(int x = -1, int y = -1, QString channel = QString());
219 	QString createNewCheckBox(int x = -1, int y = -1, QString channel = QString());
220 	QString createNewMenu(int x = -1, int y = -1, QString channel = QString());
221 	QString createNewMeter(int x = -1, int y = -1, QString channel = QString());
222 	QString createNewConsole(int x = -1, int y = -1, QString channel = QString());
223 	QString createNewGraph(int x = -1, int y = -1, QString channel = QString());
224 	QString createNewScope(int x = -1, int y = -1, QString channel = QString());
225     QString createNewTableDisplay(int x= -1, int y= -1, QString channel = QString());
226 
227 	void clearWidgets();
228 	void clearWidgetLayout();
229 
230 
231 	QStringList getUuids();
232 	QStringList listProperties(QString widgetid); // widgetid can be eihter uuid (prefered) or channel
233 	bool destroyWidget(QString widgetid);
234 
235 	void propertiesDialog();
236 	void applyProperties();
237 	void selectBgColor();
238 	void setEditEnabled(bool enabled);
239 	void setEditMode(bool active);
240 	void deselectAll();
241 	void selectAll();
242 	void widgetMoved(QPair<int, int>);
243 	void widgetResized(QPair<int, int>);
244 	void mousePressEventParent(QMouseEvent *event); // To receive events from ancestors when outside the widget area
245 	void mouseReleaseEventParent(QMouseEvent *event);
246 	void mouseMoveEventParent(QMouseEvent *event);
247 	void selectionChanged(QRect selection);
248 	QSize getUsedSize();
249 	void adjustLayoutSize();
250 	void adjustWidgetSize();
251 	void setModified(bool mod = true);
252 	void setMouseOffset(int x, int y);
253 
254 	// Preset slots
255 	void loadPreset(); // Show dialog and ask
256 	void loadPresetFromAction();  // Triggered from menu item
257 	void loadPresetFromItem(QTreeWidgetItem * item, int column);  // Triggered from tree widget
258 	void loadPreset(int num);
259 	void loadPresetFromIndex(int index);
260 	void newPreset(); // Show dialog asking for name
261 	//    void newPreset(int num, QString name);
262 	void savePreset(); // Show dialog asking for name
263 	void savePreset(int num, QString name);
264 
265 	// Editing
266 	void copy();
267 	void cut();
268 	void paste();
269 	//    void paste(QPoint pos);
270 	void duplicate();
271 	void deleteSelected();
272     void moveSelected(int horiz, int vert, int grid=1);
273 	void undo();
274 	void redo();
275     void reloadWidgets();
276 
277 	// Alignment
278 	void alignLeft();
279 	void alignRight();
280 	void alignTop();
281 	void alignBottom();
282 	void sendToBack();
283     void sendToFront();
284 	void distributeHorizontal();
285 	void distributeVertical();
286 	void alignCenterVertical();
287 	void alignCenterHorizontal();
288 
289 	void markHistory();
290 	void createEditFrame(QuteWidget* widget);
291 
292 	void widgetChanged(QuteWidget* widget = 0);
293 	void deleteWidget(QuteWidget *widget);
294 
295 	void newValue(QPair<QString, double> channelValue);
296 	void newValue(QPair<QString, QString> channelValue);
297 	void processNewValues();
298 	void queueEvent(QString eventLine);
299 
300     void processUpdateCurve(Curve *curve);
301 	// Messages
302 	void appendMessage(QString message);
303 
304 
305 protected:
306 	virtual void mousePressEvent(QMouseEvent *event);
307 	virtual void mouseMoveEvent(QMouseEvent *event);
308 	virtual void mouseReleaseEvent(QMouseEvent *event);
309 	virtual void keyPressEvent(QKeyEvent *event);
310 	virtual void keyReleaseEvent(QKeyEvent *event);
311 	virtual void contextMenuEvent(QContextMenuEvent *event);
312     virtual void closeEvent(QCloseEvent *event);
313 	QRubberBand *selectionFrame;
314 	int startx, starty;
315 
316 private:
317 
318 	QMutex widgetsMutex;
319 	QMutex layoutMutex;
320 	QList<Curve *> newCurveBuffer;  // To store curves from Csound for widget panel Graph widgets
321 	QVector<WINDAT> curveUpdateBuffer; // FIXME move these buffers to documentpage to avoid duplication when having multiple panels
322 	int curveUpdateBufferCount;
323 	QList<Curve *> curves;
324 	QTimer updateTimer;
325 
326 	unsigned long m_ksmpscount;  // Ksmps counter for Csound engine (Really needed here?)
327 
328 	// Properties of the panel (saved to xml file)
329 	int m_posx, m_posy, m_w, m_h; // Position and size of panel (not this widget)
330 	QString m_objectName;
331 	QString m_uuid;
332 	bool m_visible;
333 
334 	// Configuration
335 	bool m_repeatKeys;
336 	bool m_xmlFormat;
337 	bool m_trackMouse;
338 	bool m_openProperties; // Open widget properties when creating widgets
339 	bool m_enableEdit; // Enable editing and properties dialog
340 	bool m_tooltips;  // Show widget tooltips
341 	int mouseX, mouseY, mouseRelX, mouseRelY, mouseBut1, mouseBut2;
342 	int xOffset, yOffset;
343 	double m_fontOffset, m_fontScaling;
344     int m_updateRate;
345 
346 	// For the properties dialog - they store the configuration data for the widget panel
347 	QPoint currentPosition;  //TODO use proper variables instead of storing data in the widgets...
348 	QCheckBox *bgCheckBox;
349 	QPushButton *bgButton;
350 	int closing; // to control timer when destroying this object
351     // XXXX: flag to control updateData
352     bool m_updating;
353 
354 	QVector<QString> m_history;  // Undo/ Redo history
355 	int m_historyIndex; // Current point in history
356 	bool m_modified;
357 	bool m_editMode;
358 	//    QString m_clipboard;
359     // Whether contained in another widget (scrollbar in widget panel or widget panel)
360     bool m_contained;
361 
362 	QVector<WidgetPreset> presets;
363 	int m_currentPreset; // If -1 no current preset
364 
365 	QList<RegisteredController> registeredControllers;
366 
367 	// Contained Widgets
368 	QVector<QuteWidget *> m_widgets;
369 	QVector<FrameWidget *> editWidgets;
370 	// These vectors must be used with care since they are not reentrant and will
371 	// cause problems when accessed simultaneously
372 	// They are pointers to widgets already in widgets vector
373 	// TODO check where these are accessed for problems
374 	QVector<QuteConsole *> consoleWidgets;
375 	QVector<QuteGraph *> graphWidgets;
376 	QVector<QuteScope *> scopeWidgets;
377 	int m_activeWidgets; // Keeps a number of widgets that can be currently accessed by value callbacks (e.g. set to 0 during paste). This is done to avoid locking the callbacks, which are called from a realtime thread
378 
379 	int parseXmlNode(QDomNode node);
380 	QString createSlider(int x, int y, int width, int height, QString widgetLine);
381 	QString createText(int x, int y, int width, int height, QString widgetLine);
382 	QString createScrollNumber(int x, int y, int width, int height, QString widgetLine);
383 	QString createLineEdit(int x, int y, int width, int height, QString widgetLine);
384 	QString createSpinBox(int x, int y, int width, int height, QString widgetLine);
385 	QString createButton(int x, int y, int width, int height, QString widgetLine);
386 	QString createKnob(int x, int y, int width, int height, QString widgetLine);
387 	QString createCheckBox(int x, int y, int width, int height, QString widgetLine);
388 	QString createMenu(int x, int y, int width, int height, QString widgetLine);
389 	QString createMeter(int x, int y, int width, int height, QString widgetLine);
390 	QString createConsole(int x, int y, int width, int height, QString widgetLine);
391 	QString createGraph(int x, int y, int width, int height, QString widgetLine);
392 	QString createScope(int x, int y, int width, int height, QString widgetLine);
393 	QString createDummy(int x, int y, int width, int height, QString widgetLine);
394     QString createTableDisplay(int x, int y, int width, int height, QString widgetLine);
395 
396 
397 	void setBackground(bool bg, QColor bgColor);
398 	FrameWidget *getEditWidget(QuteWidget *widget);
399 
400 	void registerWidgetController(QuteWidget *widget, int cc);
401 	void registerWidgetChannel(QuteWidget *widget, int chan);
402 	void unregisterWidgetController(QuteWidget *widget);
403 	void clearWidgetControllers();
404 
405 	//Undo history
406 	void clearHistory();
407 
408 	// Preset Methods
409 	int getPresetIndex(int number);
410 
411 	//XML helper functions
412 	QColor getColorFromElement(QDomElement elem);  // Converts an XML color element to a QColor structure
413 
414     QHash<QString, QuteWidgetType> m_widgetNameToType;
415 
416 private slots:
417 	void updateData();
418 	void widgetSelected(QuteWidget *widget);
419 	void widgetUnselected(QuteWidget *widget);
420 
421 signals:
422 	void selection(QRect area);
423 	void keyPressed(int key);
424 	void keyReleased(int key);
425 	void changed(); // Should be triggered whenever widgets change, to let main document know
426 	void registerScope(QuteScope *scope);
427 	void registerGraph(QuteGraph *graph);
428 	void registerButton(QuteButton *button);
429     void requestCsoundUserData(QuteWidget *widget);
430     void queueEventSignal(QString eventLine);
431 	void widgetSelectedSignal(QuteWidget *widget);
432 	void widgetUnselectedSignal(QuteWidget *widget);
433 	void showMidiLearn(QuteWidget *);
434 	void addChn_kSignal(QString channel);
435     void windowStatus(bool);
436 	//    void setWidgetClipboardSignal(QString text);  // To propagate clipboard for sharing between pages
437 };
438 
439 #endif // WIDGETLAYOUT_H
440