maindlg.cpp 24.2 KB
Newer Older
1 2 3
/*
* KmPlot - a math. function plotter for the KDE-Desktop
*
Christoph Feck's avatar
Christoph Feck committed
4
* Copyright (C) 1998, 1999, 2000, 2002  Klaus-Dieter Möller <kd.moeller@t-online.de>
David Saxton's avatar
David Saxton committed
5
*                                 2006  David Saxton <david@bluehaze.org>
6
*
7 8 9 10 11 12 13
* This file is part of the KDE Project.
* KmPlot is part of the KDE-EDU Project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
14
*
15 16 17 18
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
19
*
20 21
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
Dirk Mueller's avatar
Dirk Mueller committed
22
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23 24 25
*
*/

Peter Hedlund's avatar
Peter Hedlund committed
26 27
#include "maindlg.h"

28
// Qt includes
29
#include <QMainWindow>
Laurent Montel's avatar
Laurent Montel committed
30
#include <QPixmap>
31
#include <QSvgGenerator>
David Saxton's avatar
David Saxton committed
32
#include <QTimer>
Inge Wallin's avatar
Inge Wallin committed
33
#include <QMenu>
34 35
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QPrintDialog>
36 37

// KDE includes
Christoph Feck's avatar
Christoph Feck committed
38
#include <k4aboutdata.h>
39
#include <kconfigdialog.h>
40
#include <kconfigdialogmanager.h>
41
#include <kdebug.h>
42
#include <kedittoolbar.h>
Albert Astals Cid's avatar
Albert Astals Cid committed
43
#include <kfiledialog.h>
44
#include <kimageio.h>
45
#include <kio/netaccess.h>
46
#include <kcomponentdata.h>
47
#include <klineedit.h>
48
#include <kmessagebox.h>
49
#include <kmimetype.h>
50
#include <kstandarddirs.h>
Aaron J. Seigo's avatar
Aaron J. Seigo committed
51
#include <kstandardaction.h>
Jaison Lee's avatar
Jaison Lee committed
52
#include <ktemporaryfile.h>
53
#include <ktoolbar.h>
Laurent Montel's avatar
Laurent Montel committed
54
#include <ktoolinvocation.h>
Stephan Kulow's avatar
Stephan Kulow committed
55
#include <krecentfilesaction.h>
56
#include <kactioncollection.h>
Christoph Feck's avatar
Christoph Feck committed
57
#include <khelpclient.h>
Laurent Montel's avatar
Laurent Montel committed
58
#include <QIcon>
59
#include <kiconloader.h>
60
#include <kapplication.h>
61

62
// local includes
63
#include "calculator.h"
64
#include "functiontools.h"
65
#include "functioneditor.h"
66
#include "kprinterdlg.h"
67
#include "kconstanteditor.h"
68
#include "xparser.h"
69

70
#include "settings.h"
71 72
#include "ui_settingspagecolor.h"
#include "ui_settingspagefonts.h"
73
#include "ui_settingspagegeneral.h"
David Saxton's avatar
David Saxton committed
74
#include "ui_settingspagediagram.h"
75
#include "ksliderwindow.h"
76
#include "maindlgadaptor.h"
77

78 79
#include <assert.h>

80 81
class XParser;
class KmPlotIO;
82

83 84 85 86 87 88

class SettingsPageColor : public QWidget, public Ui::SettingsPageColor
{
    public:
        SettingsPageColor( QWidget * parent = 0 )
    : QWidget( parent )
89 90 91 92
        {
			setupUi(this);
			layout()->setMargin(0);
		}
93 94 95 96 97 98
};

class SettingsPageFonts : public QWidget, public Ui::SettingsPageFonts
{
    public:
        SettingsPageFonts( QWidget * parent = 0 )
99 100 101 102 103
	: QWidget( parent )
		{
			setupUi(this);
			layout()->setMargin(0);
		}
104 105 106 107 108 109
};

class SettingsPageGeneral : public QWidget, public Ui::SettingsPageGeneral
{
    public:
        SettingsPageGeneral( QWidget * parent = 0 )
110 111 112
	: QWidget( parent )
		{
			setupUi(this);
113
                        layout()->setMargin(0);
114
		}
115 116
};

David Saxton's avatar
David Saxton committed
117 118 119 120 121
class SettingsPageDiagram : public QWidget, public Ui::SettingsPageDiagram
{
	public:
		SettingsPageDiagram( QWidget * parent = 0 )
	: QWidget( parent )
122 123 124 125
		{
			setupUi(this);
			layout()->setMargin(0);
		}
David Saxton's avatar
David Saxton committed
126 127
};

128
bool MainDlg::oldfileversion;
129 130
MainDlg * MainDlg::m_self = 0;

131
K_PLUGIN_FACTORY( KmPlotPartFactory, registerPlugin<MainDlg>(); )
132

133
//BEGIN class MainDlg
134
MainDlg::MainDlg(QWidget *parentWidget, QObject *parent, const QVariantList& ) :
135
		KParts::ReadWritePart( parent ),
136 137 138
		m_recentFiles( 0 ),
		m_modified(false),
		m_parent(parentWidget)
Matthias Messmer's avatar
Matthias Messmer committed
139
{
140 141
	assert( !m_self ); // this class should only be constructed once
	m_self = this;
Stephan Kulow's avatar
Stephan Kulow committed
142

143
	kDebug() << "parentWidget->objectName():" << parentWidget->objectName();
Fredrik Edemar's avatar
Fredrik Edemar committed
144
	if ( QString(parentWidget->objectName()).startsWith("KmPlot") )
145 146 147 148 149 150 151 152 153 154
	{
		setXMLFile("kmplot_part.rc");
		m_readonly = false;
	}
	else
	{
		setXMLFile("kmplot_part_readonly.rc");
		m_readonly = true;
		new BrowserExtension(this); // better integration with Konqueror
	}
Stephan Kulow's avatar
Stephan Kulow committed
155

156
	m_coordsDialog = 0;
157
	m_constantEditor = 0;
Inge Wallin's avatar
Inge Wallin committed
158 159
	m_popupmenu = new QMenu( parentWidget );
	m_newPlotMenu = new QMenu( parentWidget );
160
	(void) new View( m_readonly, m_popupmenu, parentWidget );
161
	connect( View::self(), SIGNAL( setStatusBarText(const QString &)), this, SLOT( setReadOnlyStatusBarText(const QString &) ) );
Stephan Kulow's avatar
Stephan Kulow committed
162

163
	m_functionEditor = 0;
164 165
	if ( !m_readonly )
	{
166
		m_functionEditor = new FunctionEditor( m_newPlotMenu, parentWidget );
167 168
		static_cast<QMainWindow*>(parentWidget)->addDockWidget( Qt::LeftDockWidgetArea, m_functionEditor );
	}
Stephan Kulow's avatar
Stephan Kulow committed
169

170 171
	setWidget( View::self() );
	View::self()->setFocusPolicy(Qt::ClickFocus);
172
	m_functionTools = new FunctionTools(m_parent);
173
	m_calculator = new Calculator( m_parent );
174
	setupActions();
175
	XParser::self()->constants()->load();
176
	kmplotio = new KmPlotIO();
Laurent Montel's avatar
Laurent Montel committed
177
	m_config = KSharedConfig::openConfig();
Stephan Kulow's avatar
ported  
Stephan Kulow committed
178
	m_recentFiles->loadEntries( m_config->group( QString() ) );
Stephan Kulow's avatar
Stephan Kulow committed
179 180


David Saxton's avatar
David Saxton committed
181 182 183 184 185 186
	//BEGIN undo/redo stuff
	m_currentState = kmplotio->currentState();
	m_saveCurrentStateTimer = new QTimer( this );
	m_saveCurrentStateTimer->setSingleShot( true );
	connect( m_saveCurrentStateTimer, SIGNAL(timeout()), this, SLOT(saveCurrentState()) );
	//END undo/redo stuff
Stephan Kulow's avatar
Stephan Kulow committed
187 188 189



190 191
	// Allow config manager to read from equation edits
	KConfigDialogManager::changedMap()->insert( "EquationEdit", SIGNAL(textEdited(const QString &)) );
192
	// Let's create a Configure Diloag
193
	m_settingsDialog = new KConfigDialog( parentWidget, "settings", Settings::self() );
Christoph Feck's avatar
Christoph Feck committed
194 195
//FIXME port to KF5
//	m_settingsDialog->setHelp("general-config");
196

197
	// create and add the page(s)
198 199 200
	m_generalSettings = new SettingsPageGeneral( View::self() );
	m_colorSettings = new SettingsPageColor( View::self() );
	m_fontsSettings = new SettingsPageFonts( View::self() );
David Saxton's avatar
David Saxton committed
201
	m_diagramSettings = new SettingsPageDiagram( View::self() );
202

203 204 205 206
	// Make sure the dialog is at a good default size (hmm kdialog should do this automatically?)
	QSize minSize = m_generalSettings->layout()->minimumSize()
			.expandedTo( m_colorSettings->layout()->minimumSize() )
			.expandedTo( m_fontsSettings->layout()->minimumSize() )
207
			.expandedTo( m_diagramSettings->layout()->minimumSize() );
208
	m_generalSettings->setMinimumSize( minSize );
Stephan Kulow's avatar
Stephan Kulow committed
209

Pino Toscano's avatar
Pino Toscano committed
210
	m_settingsDialog->addPage( m_generalSettings, i18n("General"), "kmplot", i18n("General Settings") );
David Saxton's avatar
David Saxton committed
211
	m_settingsDialog->addPage( m_diagramSettings, i18n("Diagram"), "coords", i18n("Diagram Appearance") );
Pino Toscano's avatar
Pino Toscano committed
212 213
	m_settingsDialog->addPage( m_colorSettings, i18n("Colors"), "preferences-desktop-color", i18n("Colors") );
	m_settingsDialog->addPage( m_fontsSettings, i18n("Fonts"), "preferences-desktop-font", i18n("Fonts") );
214 215
	// User edited the configuration - update your local copies of the
	// configuration data
216
	connect( m_settingsDialog, SIGNAL( settingsChanged( const QString &) ), View::self(), SLOT(drawPlot() ) );
217 218 219


    new MainDlgAdaptor(this);
220
    QDBusConnection::sessionBus().registerObject("/maindlg", this);
221

222 223 224 225
}

MainDlg::~MainDlg()
{
Stephan Kulow's avatar
ported  
Stephan Kulow committed
226
        m_recentFiles->saveEntries( m_config->group( QString() ) );
227
	XParser::self()->constants()->save();
228
	delete kmplotio;
229 230 231
}

void MainDlg::setupActions()
Matthias Messmer's avatar
Matthias Messmer committed
232
{
233
	// standard actions
Inge Wallin's avatar
Inge Wallin committed
234
        m_recentFiles = KStandardAction::openRecent( this, SLOT( slotOpenRecent( const QUrl& ) ), this );
Christoph Feck's avatar
Christoph Feck committed
235
        actionCollection()->addAction( "file_open_recent", m_recentFiles );
236
	actionCollection()->addAction( KStandardAction::Print, "file_print", this, SLOT( slotPrint() ) );
Aaron J. Seigo's avatar
Aaron J. Seigo committed
237 238
	KStandardAction::save( this, SLOT( slotSave() ), actionCollection() );
	KStandardAction::saveAs( this, SLOT( slotSaveas() ), actionCollection() );
239

240
	QAction *prefs  = KStandardAction::preferences( this, SLOT( slotSettings() ), actionCollection());
241
	prefs->setText( i18n( "Configure KmPlot..." ) );
242

243
	// KmPlot specific actions
Stephan Kulow's avatar
Stephan Kulow committed
244

245
	//BEGIN file menu
246 247
	QAction * exportAction = actionCollection()->addAction( "export" );
        exportAction->setText( i18n( "E&xport..." ) );
Christoph Feck's avatar
Christoph Feck committed
248
        exportAction->setIcon( QIcon::fromTheme( "document-export" ) );
249 250 251
	connect( exportAction, SIGNAL(triggered(bool)), this, SLOT( slotExport() ) );
	//END file menu

Stephan Kulow's avatar
Stephan Kulow committed
252

David Saxton's avatar
David Saxton committed
253
	//BEGIN edit menu
Aaron J. Seigo's avatar
Aaron J. Seigo committed
254
	m_undoAction = KStandardAction::undo( this, SLOT(undo()), actionCollection() );
David Saxton's avatar
David Saxton committed
255
	m_undoAction->setEnabled( false );
Stephan Kulow's avatar
Stephan Kulow committed
256

Aaron J. Seigo's avatar
Aaron J. Seigo committed
257
	m_redoAction = KStandardAction::redo( this, SLOT(redo()), actionCollection() );
David Saxton's avatar
David Saxton committed
258
	m_redoAction->setEnabled( false );
Stephan Kulow's avatar
Stephan Kulow committed
259

260 261
	QAction * editAxes = actionCollection()->addAction( "editaxes" );
        editAxes->setText( i18n( "&Coordinate System..." ) );
Christoph Feck's avatar
Christoph Feck committed
262
	editAxes->setIcon( QIcon::fromTheme("coords.png") );
David Saxton's avatar
David Saxton committed
263
	connect( editAxes, SIGNAL(triggered(bool)), this, SLOT( editAxes() ) );
264

265 266
	QAction * editConstants = actionCollection()->addAction( "editconstants" );
        editConstants->setText( i18n( "&Constants..." ) );
Christoph Feck's avatar
Christoph Feck committed
267
	editConstants->setIcon( QIcon::fromTheme("editconstants.png") );
268
	connect( editConstants, SIGNAL(triggered(bool)), this, SLOT( editConstants() ) );
David Saxton's avatar
David Saxton committed
269
	//END edit menu
Stephan Kulow's avatar
Stephan Kulow committed
270 271


272
	//BEGIN view menu
David Saxton's avatar
David Saxton committed
273
	/// \todo check that new shortcuts work
Stephan Kulow's avatar
Stephan Kulow committed
274

Christoph Feck's avatar
Christoph Feck committed
275
	QAction * zoomIn = actionCollection()->addAction( "zoom_in" );
276
        zoomIn->setText( i18n("Zoom &In") );
Christoph Feck's avatar
Christoph Feck committed
277
	actionCollection()->setDefaultShortcut( zoomIn, QKeySequence(Qt::ControlModifier | Qt::Key_1) );
Christoph Feck's avatar
Christoph Feck committed
278
	zoomIn->setIcon( QIcon::fromTheme("zoom-in") );
279
	connect( zoomIn, SIGNAL(triggered(bool)), View::self(), SLOT(zoomIn()) );
Stephan Kulow's avatar
Stephan Kulow committed
280

Christoph Feck's avatar
Christoph Feck committed
281
	QAction * zoomOut = actionCollection()->addAction( "zoom_out" );
282
        zoomOut->setText(i18n("Zoom &Out"));
Christoph Feck's avatar
Christoph Feck committed
283
	actionCollection()->setDefaultShortcut( zoomOut, QKeySequence(Qt::ControlModifier | Qt::Key_2) );
Christoph Feck's avatar
Christoph Feck committed
284
	zoomOut->setIcon( QIcon::fromTheme("zoom-out") );
285
	connect( zoomOut, SIGNAL(triggered(bool)), View::self(), SLOT( zoomOut() ) );
Stephan Kulow's avatar
Stephan Kulow committed
286

287 288
	QAction * zoomTrig = actionCollection()->addAction( "zoom_trig" );
        zoomTrig->setText( i18n("&Fit Widget to Trigonometric Functions") );
289
	connect( zoomTrig, SIGNAL(triggered(bool)), View::self(), SLOT( zoomToTrigonometric() ) );
Stephan Kulow's avatar
Stephan Kulow committed
290

291 292
	QAction * resetView = actionCollection()->addAction( "reset_view" );
	resetView->setText( i18n( "Reset View" ) );
Christoph Feck's avatar
Christoph Feck committed
293
	resetView->setIcon( QIcon::fromTheme("resetview") );
294
	connect( resetView, SIGNAL(triggered(bool)), this, SLOT( slotResetView() ) );
295
	//END view menu
Stephan Kulow's avatar
Stephan Kulow committed
296 297


298
	//BEGIN tools menu
299 300
	QAction *mnuCalculator = actionCollection()->addAction( "calculator" );
	mnuCalculator->setText( i18n( "Calculator") );
Christoph Feck's avatar
Christoph Feck committed
301
	mnuCalculator->setIcon( QIcon::fromTheme("system-run") );
302
	connect( mnuCalculator, SIGNAL(triggered(bool)), this, SLOT( calculator() ) );
Stephan Kulow's avatar
Stephan Kulow committed
303

304 305
	QAction *mnuArea = actionCollection()->addAction( "grapharea" );
        mnuArea->setText( i18n( "Plot &Area..." ) );
306
	connect( mnuArea, SIGNAL(triggered(bool)),this, SLOT( graphArea() )  );
Stephan Kulow's avatar
Stephan Kulow committed
307

308 309
	QAction *mnuMaxValue = actionCollection()->addAction( "maximumvalue" );
        mnuMaxValue->setText( i18n( "Find Ma&ximum..." ) );
Christoph Feck's avatar
Christoph Feck committed
310
	mnuMaxValue->setIcon( QIcon::fromTheme("maximum") );
311
	connect( mnuMaxValue, SIGNAL(triggered(bool)), this, SLOT( findMaximumValue() ) );
Stephan Kulow's avatar
Stephan Kulow committed
312

313 314
	QAction *mnuMinValue = actionCollection()->addAction( "minimumvalue" );
        mnuMinValue->setText( i18n( "Find Mi&nimum..." ) );
Christoph Feck's avatar
Christoph Feck committed
315
	mnuMinValue->setIcon( QIcon::fromTheme("minimum") );
316
	connect( mnuMinValue, SIGNAL(triggered(bool)), this, SLOT( findMinimumValue() ) );
317
	//END tools menu
318

Stephan Kulow's avatar
Stephan Kulow committed
319

320
	//BEGIN help menu
321 322
	QAction * namesAction = actionCollection()->addAction( "names" );
        namesAction->setText( i18n( "Predefined &Math Functions" ) );
Christoph Feck's avatar
Christoph Feck committed
323
	namesAction->setIcon( QIcon::fromTheme("functionhelp") );
324 325
	connect( namesAction, SIGNAL(triggered(bool)), this, SLOT( slotNames() ) );
	//END help menu
Stephan Kulow's avatar
Stephan Kulow committed
326 327


328
	//BEGIN new plots menu
329 330
	QAction * newFunction = actionCollection()->addAction( "newcartesian" );
        newFunction->setText( i18n( "Cartesian Plot" ) );
Christoph Feck's avatar
Christoph Feck committed
331
	newFunction->setIcon( QIcon::fromTheme("newfunction") );
332
	connect( newFunction, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createCartesian() ) );
333
	m_newPlotMenu->addAction( newFunction );
Stephan Kulow's avatar
Stephan Kulow committed
334

335 336
	QAction * newParametric = actionCollection()->addAction( "newparametric" );
        newParametric->setText( i18n( "Parametric Plot" ) );
Christoph Feck's avatar
Christoph Feck committed
337
	newParametric->setIcon( QIcon::fromTheme("newparametric") );
338
	connect( newParametric, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createParametric() ) );
339
	m_newPlotMenu->addAction( newParametric );
Stephan Kulow's avatar
Stephan Kulow committed
340

341 342
	QAction * newPolar = actionCollection()->addAction( "newpolar" );
        newPolar->setText( i18n( "Polar Plot" ) );
Christoph Feck's avatar
Christoph Feck committed
343
	newPolar->setIcon( QIcon::fromTheme("newpolar") );
344
	connect( newPolar, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createPolar() ) );
345
	m_newPlotMenu->addAction( newPolar );
Stephan Kulow's avatar
Stephan Kulow committed
346

347 348
	QAction * newImplicit = actionCollection()->addAction( "newimplicit" );
        newImplicit->setText( i18n( "Implicit Plot" ) );
Christoph Feck's avatar
Christoph Feck committed
349
	newImplicit->setIcon( QIcon::fromTheme("newimplicit") );
350 351
	connect( newImplicit, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createImplicit() ) );
	m_newPlotMenu->addAction( newImplicit );
Stephan Kulow's avatar
Stephan Kulow committed
352

353 354
	QAction * newDifferential = actionCollection()->addAction( "newdifferential" );
        newDifferential->setText( i18n( "Differential Plot" ) );
Christoph Feck's avatar
Christoph Feck committed
355
	newDifferential->setIcon( QIcon::fromTheme("newdifferential") );
356 357
	connect( newDifferential, SIGNAL(triggered(bool)), m_functionEditor, SLOT( createDifferential() ) );
	m_newPlotMenu->addAction( newDifferential );
358
	//END new plots menu
Stephan Kulow's avatar
Stephan Kulow committed
359 360


361 362
	View::self()->m_menuSliderAction = actionCollection()->add<KToggleAction>( "options_configure_show_sliders" );
        View::self()->m_menuSliderAction->setText( i18n( "Show Sliders" ) );
363
	connect( View::self()->m_menuSliderAction, SIGNAL(triggered(bool)), this, SLOT( toggleShowSliders() ) );
Stephan Kulow's avatar
Stephan Kulow committed
364

365

366
	//BEGIN function popup menu
367 368
	QAction *mnuEdit = actionCollection()->addAction( "mnuedit"  );
        mnuEdit->setText(i18n("&Edit"));
369
	m_firstFunctionAction = mnuEdit;
Christoph Feck's avatar
Christoph Feck committed
370
	mnuEdit->setIcon( QIcon::fromTheme("editplots") );
371 372
	connect(mnuEdit , SIGNAL(triggered(bool)), View::self(), SLOT( editCurrentPlot() ) );
	m_popupmenu->addAction( mnuEdit );
373 374 375

	QAction *mnuHide = actionCollection()->addAction( "mnuhide" );
        mnuHide->setText( i18n("&Hide") );
376
	connect( mnuHide, SIGNAL(triggered(bool)), View::self(), SLOT( hideCurrentFunction() ) );
377
	m_popupmenu->addAction( mnuHide );
Stephan Kulow's avatar
Stephan Kulow committed
378

379 380
	QAction *mnuRemove = actionCollection()->addAction( "mnuremove"  );
        mnuRemove->setText(i18n("&Remove"));
Christoph Feck's avatar
Christoph Feck committed
381
	mnuRemove->setIcon( QIcon::fromTheme("edit-delete") );
382
	connect( mnuRemove, SIGNAL(triggered(bool)), View::self(), SLOT( removeCurrentPlot() ) );
383
	m_popupmenu->addAction( mnuRemove );
Stephan Kulow's avatar
Stephan Kulow committed
384

David Saxton's avatar
David Saxton committed
385
	m_popupmenu->addSeparator();
Stephan Kulow's avatar
Stephan Kulow committed
386

387 388
	QAction * animateFunction = actionCollection()->addAction( "animateFunction" );
        animateFunction->setText(i18n("Animate Plot..."));
389 390
	connect( animateFunction, SIGNAL(triggered(bool)), View::self(), SLOT( animateFunction() ) );
	m_popupmenu->addAction( animateFunction );
391
	m_popupmenu->addSeparator();
Stephan Kulow's avatar
Stephan Kulow committed
392

393
	m_popupmenu->addAction( mnuCalculator );
394 395 396
	m_popupmenu->addAction( mnuMinValue );
	m_popupmenu->addAction( mnuMaxValue );
	m_popupmenu->addAction( mnuArea );
397
	//END function popup menu
398
}
399 400


David Saxton's avatar
David Saxton committed
401 402
void MainDlg::undo()
{
Thiago Macieira's avatar
Thiago Macieira committed
403
	kDebug() ;
Stephan Kulow's avatar
Stephan Kulow committed
404

David Saxton's avatar
David Saxton committed
405 406
	if ( m_undoStack.isEmpty() )
		return;
Stephan Kulow's avatar
Stephan Kulow committed
407

David Saxton's avatar
David Saxton committed
408 409
	m_redoStack.push( m_currentState );
	m_currentState = m_undoStack.pop();
Stephan Kulow's avatar
Stephan Kulow committed
410

David Saxton's avatar
David Saxton committed
411
	kmplotio->restore( m_currentState );
412
	View::self()->drawPlot();
Stephan Kulow's avatar
Stephan Kulow committed
413

David Saxton's avatar
David Saxton committed
414 415 416 417 418 419 420
	m_undoAction->setEnabled( !m_undoStack.isEmpty() );
	m_redoAction->setEnabled( true );
}


void MainDlg::redo()
{
Thiago Macieira's avatar
Thiago Macieira committed
421
	kDebug() ;
Stephan Kulow's avatar
Stephan Kulow committed
422

David Saxton's avatar
David Saxton committed
423 424
	if ( m_redoStack.isEmpty() )
		return;
Stephan Kulow's avatar
Stephan Kulow committed
425

David Saxton's avatar
David Saxton committed
426 427
	m_undoStack.push( m_currentState );
	m_currentState = m_redoStack.pop();
Stephan Kulow's avatar
Stephan Kulow committed
428

David Saxton's avatar
David Saxton committed
429
	kmplotio->restore( m_currentState );
430
	View::self()->drawPlot();
Stephan Kulow's avatar
Stephan Kulow committed
431

David Saxton's avatar
David Saxton committed
432 433 434 435 436 437 438 439 440 441 442 443 444 445
	m_undoAction->setEnabled( true );
	m_redoAction->setEnabled( !m_redoStack.isEmpty() );
}


void MainDlg::requestSaveCurrentState()
{
	m_saveCurrentStateTimer->start( 0 );
}
void MainDlg::saveCurrentState( )
{
	m_redoStack.clear();
	m_undoStack.push( m_currentState );
	m_currentState = kmplotio->currentState();
Stephan Kulow's avatar
Stephan Kulow committed
446

David Saxton's avatar
David Saxton committed
447 448 449
	// limit stack size to 100 items
	while ( m_undoStack.count() > 100 )
		m_undoStack.pop_front();
Stephan Kulow's avatar
Stephan Kulow committed
450

David Saxton's avatar
David Saxton committed
451 452
	m_undoAction->setEnabled( true );
	m_redoAction->setEnabled( false );
Stephan Kulow's avatar
Stephan Kulow committed
453

454
	m_modified = true;
David Saxton's avatar
David Saxton committed
455 456 457
}


458 459 460 461 462 463 464 465 466 467
void MainDlg::resetUndoRedo()
{
	m_redoStack.clear();
	m_undoStack.clear();
	m_currentState = kmplotio->currentState();
	m_undoAction->setEnabled( false );
	m_redoAction->setEnabled( false );
}


468 469 470 471
bool MainDlg::checkModified()
{
	if( m_modified )
	{
472
		int saveit = KMessageBox::warningYesNoCancel( m_parent, i18n( "The plot has been modified.\n"
473
		             "Do you want to save it?" ), QString(), KStandardGuiItem::save(), KStandardGuiItem::discard() );
474 475
		switch( saveit )
		{
476 477 478 479 480 481
			case KMessageBox::Yes:
				slotSave();
				if ( m_modified) // the user didn't saved the file
					return false;
				break;
			case KMessageBox::Cancel:
482 483 484 485 486
				return false;
		}
	}
	return true;
}
David Saxton's avatar
David Saxton committed
487 488


489
void MainDlg::slotSave()
Matthias Messmer's avatar
Matthias Messmer committed
490
{
491
	if ( !m_modified || m_readonly) //don't save if no changes are made or readonly is enabled
492
		return;
493
	if ( url().isEmpty() )            // if there is no file name set yet
494
		slotSaveas();
495
	else
496
	{
497 498
		if ( !m_modified) //don't save if no changes are made
			return;
499

500 501
		if ( oldfileversion)
		{
502
			if ( KMessageBox::warningContinueCancel( m_parent, i18n( "This file is saved with an old file format; if you save it, you cannot open the file with older versions of KmPlot. Are you sure you want to continue?" ), QString(), KGuiItem(i18n("Save New Format")) ) == KMessageBox::Cancel)
503 504
				return;
		}
505
		kmplotio->save( this->url() );
506
		kDebug() << "saved";
507 508
		m_modified = false;
	}
Matthias Messmer's avatar
Matthias Messmer committed
509

Matthias Messmer's avatar
Matthias Messmer committed
510
}
511

512
void MainDlg::slotSaveas()
Matthias Messmer's avatar
Matthias Messmer committed
513
{
514 515
	if (m_readonly)
		return;
516
	const QUrl url = KFileDialog::getSaveUrl(QUrl::fromLocalFile(QDir::currentPath()),
Inge Wallin's avatar
Inge Wallin committed
517 518
			    i18n( "*.fkt|KmPlot Files (*.fkt)\n*|All Files" ),
			    m_parent, i18n( "Save As" ) );
519

520 521
	if ( url.isEmpty() )
		return;
522

523
	bool exists = KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, m_parent );
524
	if ( exists )
525
	{
526
		// check if file exists and overwriting is ok.
527

528
		int answer = KMessageBox::warningContinueCancel( m_parent, i18n( "A file named \"%1\" already exists. Are you sure you want to continue and overwrite this file?", url.url()), i18n( "Overwrite File?" ), KStandardGuiItem::overwrite() );
529

530
		if ( answer != KMessageBox::Continue )
531
			return;
532
	}
533

534 535 536 537
	if ( !kmplotio->save( url ) )
		KMessageBox::error(m_parent, i18n("The file could not be saved") );
	else
	{
538
		setUrl(url);
539
		m_recentFiles->addUrl( url );
Inge Wallin's avatar
Inge Wallin committed
540
		setWindowCaption( QUrl(this->url()).toString() );
541
		m_modified = false;
542
	}
Matthias Messmer's avatar
Matthias Messmer committed
543
}
544

545
void MainDlg::slotExport()
546
{
547 548
	QString filter = KImageIO::pattern( KImageIO::Writing );
	filter += i18n("\n*.svg|Scalable Vector Graphics");
549

550
	QUrl url = KFileDialog::getSaveUrl(QUrl::fromLocalFile(QDir::currentPath()), filter, m_parent, i18n( "Export as Image" ) );
551

552
	if ( !url.isValid() )
553
		return;
554
	bool exists = KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, m_parent );
555 556 557 558
	if ( exists )
	{
		// check if file exists and overwriting is ok.

559
		int answer = KMessageBox::warningContinueCancel( m_parent, i18n( "A file named \"%1\" already exists. Are you sure you want to continue and overwrite this file?", url.url()), i18n( "Overwrite File?" ), KStandardGuiItem::overwrite() );
560 561 562 563

		if ( answer != KMessageBox::Continue )
			return;
	}
564

565
	KMimeType::Ptr mimeType = KMimeType::findByUrl( url );
Thiago Macieira's avatar
Thiago Macieira committed
566
	kDebug() << "mimetype: " << mimeType->name();
567

568
	bool isSvg = mimeType->name() == "image/svg+xml";
569

570
	if ( !KImageIO::isSupported( mimeType->name(), KImageIO::Writing ) && !isSvg )
571
	{
572
		KMessageBox::sorry( m_parent, i18n( "Sorry, this file format is not supported." ) );
573
		return;
574
	};
Stephan Kulow's avatar
Stephan Kulow committed
575

576
	bool saveOk = true;
577

578
	if ( isSvg )
579
	{
580 581
		QSvgGenerator img;
		img.setSize( View::self()->size() );
582

583 584
		QFile file;
		KTemporaryFile tmp;
585

586
		if ( url.isLocalFile() )
587
		{
588
			file.setFileName( url.toLocalFile() );
589 590
			img.setOutputDevice( &file );
		}
591 592
		else
		{
593 594
			tmp.setSuffix( ".svg" );
			img.setOutputDevice( &tmp );
595
		}
596

597
		View::self()->draw( &img, View::SVG );
598

599 600
		if ( !url.isLocalFile() )
			saveOk &= KIO::NetAccess::upload(tmp.fileName(), url, 0);
601
	}
602
	else
603
	{
604 605
		QPixmap img( View::self()->size() );
		View::self()->draw( & img, View::Pixmap );
606

607 608 609
		QStringList types = KImageIO::typeForMime( mimeType->name() );
		if ( types.isEmpty() )
			return; // TODO error dialog?
610

611
		if ( url.isLocalFile() )
612
			saveOk = img.save( url.toLocalFile(), types.at(0).toLatin1() );
613
		else
614
		{
Jaison Lee's avatar
Jaison Lee committed
615 616 617 618
			KTemporaryFile tmp;
			tmp.open();
			img.save( tmp.fileName(), types.at(0).toLatin1() );
			saveOk = KIO::NetAccess::upload(tmp.fileName(), url, 0);
619 620
		}
	}
621

622
	if ( !saveOk )
Inge Wallin's avatar
Inge Wallin committed
623 624 625
	    KMessageBox::error(m_parent,
			       i18n("Sorry, something went wrong while saving to image \"%1\"",
				    url.toString()));
626
}
627 628


629
bool MainDlg::openFile()
Matthias Messmer's avatar
Matthias Messmer committed
630
{
631
	if (url()==m_currentfile || !kmplotio->load( url() ) )
632
	{
633
		m_recentFiles->removeUrl( url() ); //remove the file from the recent-opened-file-list
Inge Wallin's avatar
Inge Wallin committed
634
		setUrl(QUrl());
635 636
		return false;
	}
637

638
	m_currentfile = url();
639 640
	m_recentFiles->addUrl( url() );
	setWindowCaption( url().toDisplayString() );
641
	resetUndoRedo();
642 643
	View::self()->updateSliders();
	View::self()->drawPlot();
644
	return true;
Matthias Messmer's avatar
Matthias Messmer committed
645 646
}

647 648 649 650 651 652
bool MainDlg::saveFile()
{
    slotSave();
    return !isModified();
}

Inge Wallin's avatar
Inge Wallin committed
653
void MainDlg::slotOpenRecent( const QUrl &url )
Matthias Messmer's avatar
Matthias Messmer committed
654
{
655
 	if( isModified() || !this->url().isEmpty() ) // open the file in a new window
656
 	{
657
		QDBusReply<void> reply = QDBusInterface( QDBusConnection::sessionBus().baseService(), "/kmplot", "org.kde.kmplot.KmPlot" ).call( QDBus::Block, "openFileInNewWindow", url.url() );
658 659 660 661 662 663 664 665
		return;
	}

	if ( !kmplotio->load( url ) ) //if the loading fails
	{
		m_recentFiles->removeUrl(url ); //remove the file from the recent-opened-file-list
		return;
	}
666 667
    m_currentfile = url;
    setUrl(url);
668
    m_recentFiles->setCurrentItem(-1); //don't select the item in the open-recent menu
Inge Wallin's avatar
Inge Wallin committed
669
    setWindowCaption( QUrl(this->url()).toString() );
670
	resetUndoRedo();
671 672
    View::self()->updateSliders();
    View::self()->drawPlot();
673
}
674

675
void MainDlg::slotPrint()
676
{
677
	QPrinter prt( QPrinter::PrinterResolution );
678
	prt.setResolution( 72 );
679 680
	KPrinterDlg* printdlg = new KPrinterDlg( m_parent );
	printdlg->setObjectName( "KmPlot page" );
681 682
	QPrintDialog *printDialog = new QPrintDialog( &prt, m_parent );
	printDialog->setOptionTabs( QList<QWidget*>() << printdlg );
683 684 685 686 687 688 689 690
	printDialog->setWindowTitle( i18n("Print Plot") );

	if (printDialog->exec())
	{
		View::self()->setPrintHeaderTable( printdlg->printHeaderTable() );
		View::self()->setPrintBackground( printdlg->printBackground() );
		View::self()->setPrintWidth( printdlg->printWidth() );
		View::self()->setPrintHeight( printdlg->printHeight() );
691
		View::self()->draw(&prt, View::Printer);
692
	}
Laurent Montel's avatar
Laurent Montel committed
693
        delete printDialog;
694 695
}

696

697 698
void MainDlg::editAxes()
{
699
	coordsDialog()->show();
700 701 702
}


703 704 705 706
void MainDlg::editConstants()
{
	if ( !m_constantEditor)
		m_constantEditor = new KConstantEditor(m_parent);
707

708 709 710 711
	m_constantEditor->show();
}


712 713 714 715 716 717 718 719 720
void MainDlg::editConstantsModal(QWidget *parent)
{
	delete m_constantEditor;
	m_constantEditor = new KConstantEditor(parent);

	m_constantEditor->setModal(true);
	m_constantEditor->show();
}

721
void MainDlg::slotNames()
Matthias Messmer's avatar
Matthias Messmer committed
722
{
Christoph Feck's avatar
Christoph Feck committed
723
	KHelpClient::invokeHelp( "func-predefined", "kmplot" );
724 725 726
}


727
void MainDlg::slotResetView()
Matthias Messmer's avatar
Matthias Messmer committed
728
{