1
/***************************************************************************
2
rkworkplace - description
4
begin : Thu Sep 21 2006
5
copyright : (C) 2006 by Thomas Friedrichsmeier
6
email : tfry@users.sourceforge.net
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
18
#include "rkworkplace.h"
20
#include <kparts/partmanager.h>
21
#include <kmessagebox.h>
23
#include <kiconloader.h>
25
#include "detachedwindowcontainer.h"
26
#include "rkcommandeditorwindow.h"
27
#include "rkhtmlwindow.h"
28
#include "rkworkplaceview.h"
29
#include "../core/robject.h"
30
#include "../core/rcontainerobject.h"
31
#include "../core/robjectlist.h"
32
#include "../dataeditor/rkeditor.h"
33
#include "../dataeditor/rkeditordataframe.h"
34
#include "../dataeditor/rkeditordataframepart.h"
35
#include "../settings/rksettingsmoduleoutput.h"
36
#include "../rbackend/rinterface.h"
37
#include "../rbackend/rcommand.h"
38
#include "../rkglobals.h"
39
#include "../rkward.h"
43
#define RESTORE_WORKPLACE_COMMAND 1
46
RKWorkplace *RKWorkplace::main_workplace = 0;
48
RKWorkplace::RKWorkplace (QWidget *parent) : QObject (parent) {
50
RK_ASSERT (main_workplace == 0);
52
main_workplace = this;
53
wview = new RKWorkplaceView (parent);
56
RKWorkplace::~RKWorkplace () {
59
// closeAll (); // not needed, as the windows will autodelete themselves using QObject mechanism. Of course, closeAll () should be called *before* quitting.
62
void RKWorkplace::attachWindow (RKMDIWindow *window) {
64
RK_ASSERT (windows.find (window) != windows.end ()); // This should not happen for now.
66
window->state = RKMDIWindow::Attached;
67
view ()->addPage (window);
69
RK_ASSERT (window->getPart ());
70
RKwardApp::getApp ()->partManager ()->addPart (window->getPart ());
73
void RKWorkplace::detachWindow (RKMDIWindow *window) {
75
RK_ASSERT (windows.find (window) != windows.end ()); // Can't detach a window that is not attached
77
window->state = RKMDIWindow::Detached;
79
RK_ASSERT (window->getPart ());
80
RKwardApp::getApp ()->partManager ()->removePart (window->getPart ());
81
view ()->removePage (window);
83
DetachedWindowContainer *detached = new DetachedWindowContainer (window);
87
void RKWorkplace::addWindow (RKMDIWindow *window) {
90
windows.append (window);
91
connect (window, SIGNAL (destroyed (QObject *)), this, SLOT (windowDestroyed (QObject *)));
92
attachWindow (window);
95
bool RKWorkplace::openScriptEditor (const KURL &url, bool use_r_highlighting, bool read_only, const QString &force_caption) {
98
RKCommandEditorWindow *editor = new RKCommandEditorWindow (view (), use_r_highlighting);
100
if (!url.isEmpty ()) {
101
if (!editor->openURL (url, use_r_highlighting, read_only)) {
103
KMessageBox::messageBox (view (), KMessageBox::Error, i18n ("Unable to open \"%1\"").arg (url.prettyURL ()), i18n ("Could not open command file"));
108
if (!force_caption.isEmpty ()) editor->setCaption (force_caption);
113
void RKWorkplace::openHelpWindow (const KURL &url) {
116
RKHelpWindow *hw = new RKHelpWindow (view ());
117
if (!url.isEmpty ()) {
124
void RKWorkplace::openOutputWindow (const KURL &url) {
127
RKOutputWindow::refreshOutput (true, true);
128
if (windows.find (RKOutputWindow::getCurrentOutput ()) == windows.end ()) {
129
addWindow (RKOutputWindow::getCurrentOutput ());
133
void RKWorkplace::newOutput () {
135
RKOutputWindow::refreshOutput (RKSettingsModuleOutput::autoShow (), RKSettingsModuleOutput::autoRaise ());
136
if (RKSettingsModuleOutput::autoShow ()) {
137
if (windows.find (RKOutputWindow::getCurrentOutput ()) == windows.end ()) {
138
addWindow (RKOutputWindow::getCurrentOutput ());
143
bool RKWorkplace::canEditObject (RObject *object) {
146
if (object->isDataFrame ()) {
148
} else if (object->isVariable () && object->getContainer ()->isDataFrame ()) {
154
RKEditor *RKWorkplace::editObject (RObject *object, bool initialize_to_empty) {
157
RObject *iobj = object;
159
RKEditorDataFramePart *part = 0;
160
RKEditor *existing_editor = object->objectOpened ();
161
if (!existing_editor) {
162
if (object->isDataFrame ()) {
163
part = new RKEditorDataFramePart (0); // TODO: reverse creation logic, just as in the other classes!
164
ed = part->getEditor ();
165
// TODO: add child objects, too?
166
ed->openObject (object, initialize_to_empty);
167
} else if (object->isVariable () && object->getContainer ()->isDataFrame ()) {
168
existing_editor = object->getContainer ()->objectOpened ();
169
if (!existing_editor) {
170
iobj = object->getContainer ();
171
part = new RKEditorDataFramePart (0);
172
ed = part->getEditor ();
173
// TODO: add child objects, too?
174
ed->openObject (iobj, initialize_to_empty);
175
// ed->focusObject (obj);
180
ed->setCaption (iobj->getShortName ()); // TODO: move to editor
181
ed->setIcon (SmallIcon ("spreadsheet"));
183
ed->setFocus (); // somehow we need to call this explicitely
187
if (existing_editor) { // not strictly an else. existing_editor may be reset inside the above if
188
if (existing_editor->isAttached ()) {
189
view ()->setActivePage (existing_editor);
191
object->getContainer ()->objectOpened ()->show ();
192
object->getContainer ()->objectOpened ()->raise ();
199
void RKWorkplace::flushAllData () {
202
for (RKWorkplaceObjectList::const_iterator it = windows.constBegin (); it != windows.constEnd (); ++it) {
203
if ((*it)->type == RKMDIWindow::DataEditorWindow) {
204
static_cast<RKEditor *> (*it)->flushChanges ();
209
void RKWorkplace::closeWindow (RKMDIWindow *window) {
211
RK_ASSERT (windows.find (window) != windows.end ());
213
window->close (true); // all the rest should happen in windowDestroyed ()
216
void RKWorkplace::closeActiveWindow () {
219
RKMDIWindow *w = activeAttachedWindow ();
220
if (w) closeWindow (w);
221
else RK_ASSERT (false); // this is benign, and maybe even ok, but I'd like to see when this happens
224
RKWorkplace::RKWorkplaceObjectList RKWorkplace::getObjectList (int type, int state) {
227
RKWorkplaceObjectList ret;
228
for (RKWorkplaceObjectList::const_iterator it = windows.constBegin (); it != windows.constEnd (); ++it) {
229
if (((*it)->type & type) && ((*it)->state & state)) {
236
void RKWorkplace::closeAll (int type, int state) {
239
RKWorkplaceObjectList list_to_close = getObjectList (type, state);
240
for (RKWorkplaceObjectList::const_iterator it = list_to_close.constBegin (); it != list_to_close.constEnd (); ++it) {
245
void RKWorkplace::windowDestroyed (QObject *object) {
247
RKMDIWindow *window = static_cast<RKMDIWindow *> (object);
249
RK_ASSERT (windows.find (window) != windows.end ());
250
if (window->isAttached ()) view ()->removePage (window, true);
251
windows.remove (window);
254
RKMDIWindow *RKWorkplace::activeAttachedWindow () {
257
return (static_cast<RKMDIWindow *> (view ()->activePage ()));
260
void RKWorkplace::activateWindow (RKMDIWindow *window) {
263
window->raise (); // Does this do the trick?
266
void RKWorkplace::saveWorkplace (RCommandChain *chain) {
269
QString workplace_description = "c (";
272
for (RKWorkplaceObjectList::const_iterator it = windows.constBegin (); it != windows.constEnd (); ++it) {
273
if (first) first = false;
274
else workplace_description.append (", ");
275
workplace_description.append ((*it)->getRDescription ());
277
workplace_description = ".rk.workplace.save <- " + workplace_description + ")";
280
RKGlobals::rInterface ()->issueCommand (workplace_description, RCommand::App | RCommand::Sync, i18n ("Save Workplace layout"), 0, 0, chain);
283
void RKWorkplace::restoreWorkplace (RCommandChain *chain) {
286
RKGlobals::rInterface ()->issueCommand (".rk.workplace.save", RCommand::App | RCommand::Sync | RCommand::GetStringVector, i18n ("Restore Workplace layout"), this, RESTORE_WORKPLACE_COMMAND, chain);
289
void RKWorkplace::clearWorkplaceDescription (RCommandChain *chain) {
292
RKGlobals::rInterface ()->issueCommand ("remove (.rk.workplace.save)", RCommand::App | RCommand::Sync | RCommand::ObjectListUpdate, QString::null, 0, 0, chain);
295
void RKWorkplace::rCommandDone (RCommand *command) {
298
RK_ASSERT (command->getFlags () == RESTORE_WORKPLACE_COMMAND);
299
for (unsigned int i = 0; i < command->getDataLength (); ++i) {
300
QString desc = command->getStringVector ()[i];
301
QString type = desc.section (QChar (':'), 0, 0);
302
QString specification = desc.section (QChar (':'), 1);
304
if (type == "data") {
305
RObject *object = RObjectList::getObjectList ()->findObject (specification);
306
if (object) editObject (object, false);
307
} else if (type == "script") {
308
openScriptEditor (specification);
309
} else if (type == "output") {
310
openOutputWindow (specification);
311
} else if (type == "help") {
312
openHelpWindow (specification);
319
#include "rkworkplace.moc"