diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | ce599e4f9f94b4eb00c1b5edb85bce5431ab3df2 (patch) | |
tree | d3bb9f5d25a2dc09ca81adecf39621d871534297 /kig/kig | |
download | tdeedu-ce599e4f9f94b4eb00c1b5edb85bce5431ab3df2.tar.gz tdeedu-ce599e4f9f94b4eb00c1b5edb85bce5431ab3df2.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeedu@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kig/kig')
-rw-r--r-- | kig/kig/Makefile.am | 53 | ||||
-rw-r--r-- | kig/kig/aboutdata.h | 89 | ||||
-rw-r--r-- | kig/kig/hi128-app-kig.png | bin | 0 -> 11501 bytes | |||
-rw-r--r-- | kig/kig/hi16-app-kig.png | bin | 0 -> 777 bytes | |||
-rw-r--r-- | kig/kig/hi22-app-kig.png | bin | 0 -> 1210 bytes | |||
-rw-r--r-- | kig/kig/hi32-app-kig.png | bin | 0 -> 1848 bytes | |||
-rw-r--r-- | kig/kig/hi48-app-kig.png | bin | 0 -> 3042 bytes | |||
-rw-r--r-- | kig/kig/hi64-app-kig.png | bin | 0 -> 4472 bytes | |||
-rw-r--r-- | kig/kig/hisc-app-kig.svgz | bin | 0 -> 3640 bytes | |||
-rw-r--r-- | kig/kig/kig.cpp | 308 | ||||
-rw-r--r-- | kig/kig/kig.desktop | 121 | ||||
-rw-r--r-- | kig/kig/kig.h | 148 | ||||
-rw-r--r-- | kig/kig/kig_commands.cpp | 398 | ||||
-rw-r--r-- | kig/kig/kig_commands.h | 217 | ||||
-rw-r--r-- | kig/kig/kig_document.cc | 200 | ||||
-rw-r--r-- | kig/kig/kig_document.h | 137 | ||||
-rw-r--r-- | kig/kig/kig_iface.cpp | 31 | ||||
-rw-r--r-- | kig/kig/kig_iface.h | 37 | ||||
-rw-r--r-- | kig/kig/kig_part.cpp | 1041 | ||||
-rw-r--r-- | kig/kig/kig_part.desktop | 16 | ||||
-rw-r--r-- | kig/kig/kig_part.h | 257 | ||||
-rw-r--r-- | kig/kig/kig_view.cpp | 593 | ||||
-rw-r--r-- | kig/kig/kig_view.h | 274 | ||||
-rw-r--r-- | kig/kig/kigpartui.rc | 288 | ||||
-rw-r--r-- | kig/kig/kigui.rc | 40 | ||||
-rw-r--r-- | kig/kig/main.cpp | 144 |
26 files changed, 4392 insertions, 0 deletions
diff --git a/kig/kig/Makefile.am b/kig/kig/Makefile.am new file mode 100644 index 00000000..719886cc --- /dev/null +++ b/kig/kig/Makefile.am @@ -0,0 +1,53 @@ +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +#SUBDIRS = pics icons + +# set the include path for X, qt and KDE +INCLUDES = $(all_includes) + +# these are the headers for your project +noinst_HEADERS = kig.h kig_document.h kig_part.h kig_view.h kig_commands.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +KDE_ICON = AUTO + +# this Makefile creates both a KPart application and a KPart +######################################################################### +# APPLICATION SECTION +######################################################################### +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +bin_PROGRAMS = kig + +# the application source, library search path, and link libraries +kig_SOURCES = main.cpp kig.cpp +kig_LDFLAGS = $(KDE_RPATH) $(all_libraries) +kig_LDADD = $(LIB_KPARTS) + +# this is where the desktop file will go +xdg_apps_DATA = kig.desktop + +# this is where the shell's XML-GUI resource file goes +rcdir = $(kde_datadir)/kig +rc_DATA = kigui.rc kigpartui.rc + +######################################################################### +# KPART SECTION +######################################################################### +noinst_LTLIBRARIES = libkigparttemp.la + +# the Part's source, library search path, and link libraries +libkigparttemp_la_SOURCES = \ + kig_document.cc \ + kig_part.cpp \ + kig_view.cpp \ + kig_commands.cpp + +libkigparttemp_la_LDFLAGS = $(all_libraries) +libkigparttemp_la_LIBADD = $(LIB_KDEPRINT) $(LIB_KIO) + +# this is where the desktop file will go +partdesktopdir = $(kde_servicesdir) +partdesktop_DATA = kig_part.desktop diff --git a/kig/kig/aboutdata.h b/kig/kig/aboutdata.h new file mode 100644 index 00000000..db4f3689 --- /dev/null +++ b/kig/kig/aboutdata.h @@ -0,0 +1,89 @@ +// Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + +// 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. + +// 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. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include <kaboutdata.h> +#include <klocale.h> + +#include "config.h" + +inline KAboutData* kigAboutData( const char* name, const char* iname ) +{ + const char* version = "v" KIGVERSION; + const char* description = I18N_NOOP( "KDE Interactive Geometry" ); + + KAboutData* tmp = new KAboutData( name, iname, version, + description, KAboutData::License_GPL, + I18N_NOOP( "(C) 2002-2005, The Kig developers" ), + 0, "http://edu.kde.org/kig" ); + tmp->addAuthor("Dominique Devriese", + I18N_NOOP("Original author, long time maintainer, design and lots of code."), + "devriese@kde.org" ); + + tmp->addAuthor("Maurizio Paolini", + I18N_NOOP( "Did a lot of important work all around Kig, " + "including, but not limited to conics, cubics, " + "transformations and property tests support." ), + "paolini@dmf.unicatt.it"); + + tmp->addAuthor( "Pino Toscano", + I18N_NOOP( "Actual maintainer, Dr. Geo import filter, point and " + "line styles, Italian translation, " + "miscellaneous stuff here and there." ), + "toscano.pino@tiscali.it" ); + + tmp->addAuthor( "Franco Pasquarelli", + I18N_NOOP( "Helped a lot with the implementation of the Locus object, " + "there's quite some math involved in doing it right, and " + "Franco wrote the most difficult parts." ), + "pasqui@dmf.unicatt.it" ); + + tmp->addCredit( "Eric Depagne", + I18N_NOOP( "The French translator, who also sent me some useful " + "feedback, like feature requests and bug reports." ), + "edepagne@eso.org" ); + + tmp->addCredit("Marc Bartsch", + I18N_NOOP("Author of KGeo, where I got inspiration, " + "some source, and most of the artwork from." ), + "marc.bartsch@web.de"); + + tmp->addCredit("Christophe Devriese", + I18N_NOOP( "Domi's brother, who he got to write the algorithm for " + "calculating the center of the circle with three " + "points given." ), + "oelewapperke@ulyssis.org" ); + + tmp->addCredit("Christophe Prud'homme", + I18N_NOOP( "Sent me a patch for some bugs." ), + "prudhomm@mit.edu" ); + + tmp->addCredit("Robert Gogolok", + I18N_NOOP("Gave me some good feedback on Kig, some feature " + "requests, cleanups and style fixes, and someone " + "to chat with on irc :)" ), + "robertgogolok@gmx.de"); + + tmp->addCredit("David Vignoni", + I18N_NOOP("Responsible for the nice application SVG Icon." ), + "david80v@tin.it"); + + tmp->addCredit( "Danny Allen", + I18N_NOOP( "Responsible for the new object action icons." ), + "danny@dannyallen.co.uk" ); + + return tmp; +} diff --git a/kig/kig/hi128-app-kig.png b/kig/kig/hi128-app-kig.png Binary files differnew file mode 100644 index 00000000..48eac877 --- /dev/null +++ b/kig/kig/hi128-app-kig.png diff --git a/kig/kig/hi16-app-kig.png b/kig/kig/hi16-app-kig.png Binary files differnew file mode 100644 index 00000000..67e1d839 --- /dev/null +++ b/kig/kig/hi16-app-kig.png diff --git a/kig/kig/hi22-app-kig.png b/kig/kig/hi22-app-kig.png Binary files differnew file mode 100644 index 00000000..bb3f7359 --- /dev/null +++ b/kig/kig/hi22-app-kig.png diff --git a/kig/kig/hi32-app-kig.png b/kig/kig/hi32-app-kig.png Binary files differnew file mode 100644 index 00000000..f7d51c72 --- /dev/null +++ b/kig/kig/hi32-app-kig.png diff --git a/kig/kig/hi48-app-kig.png b/kig/kig/hi48-app-kig.png Binary files differnew file mode 100644 index 00000000..b28d3b96 --- /dev/null +++ b/kig/kig/hi48-app-kig.png diff --git a/kig/kig/hi64-app-kig.png b/kig/kig/hi64-app-kig.png Binary files differnew file mode 100644 index 00000000..e9586819 --- /dev/null +++ b/kig/kig/hi64-app-kig.png diff --git a/kig/kig/hisc-app-kig.svgz b/kig/kig/hisc-app-kig.svgz Binary files differnew file mode 100644 index 00000000..baf0f149 --- /dev/null +++ b/kig/kig/hisc-app-kig.svgz diff --git a/kig/kig/kig.cpp b/kig/kig/kig.cpp new file mode 100644 index 00000000..2429c843 --- /dev/null +++ b/kig/kig/kig.cpp @@ -0,0 +1,308 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + +#include "kig.h" +#include "kig.moc" + +#include <qevent.h> +#include <qtimer.h> + +#include <kaction.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kedittoolbar.h> +#include <kfiledialog.h> +#include <kkeydialog.h> +#include <klibloader.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstatusbar.h> +#include <kstdaction.h> +#include <ktip.h> +#include <kurl.h> +#include <kurldrag.h> + +#include <assert.h> + +Kig::Kig() + : KParts::MainWindow( 0L, "Kig" ), m_part( 0 ) +{ + // setting the configation file + config = new KConfig( "kigrc" ); + // set the shell's ui resource file + setXMLFile("kigui.rc"); + // then, setup our actions + setupActions(); + + // this routine will find and load our Part. it finds the Part by + // name which is a bad idea usually.. but it's alright in this + // case since our Part is made for this Shell + + // we use globalLibrary() because if we use python scripting, then + // we need the python symbols to be exported, in order for python to + // be able to load its dll modules.. Another part of the problem is + // that boost.python fails to link against python ( on Debian at + // least ). + KLibrary* library = KLibLoader::self()->globalLibrary("libkigpart"); + KLibFactory* factory = 0; + if ( library ) factory = library->factory(); + if (factory) + { + // now that the Part is loaded, we cast it to a Part to get + // our hands on it + m_part = static_cast<KParts::ReadWritePart*> + (factory->create(this, "kig_part", "KParts::ReadWritePart" )); + if (m_part) + { + // tell the KParts::MainWindow that this is indeed the main widget + setCentralWidget(m_part->widget()); + + // and integrate the part's GUI with the shell's + createGUI(m_part); + // finally show tip-of-day ( if the user wants it :) ) + QTimer::singleShot( 0, this, SLOT( startupTipOfDay() ) ); + } + } + else + { + // if we couldn't find our Part, we exit since the Shell by + // itself can't do anything useful + KMessageBox::error(this, i18n( "Could not find the necessary Kig library, check your installation." ) ); + KApplication::exit(); + return; + } + + // we have drag'n'drop + setAcceptDrops(true); + + // save the window settings on exit. + setAutoSaveSettings(); +} + +Kig::~Kig() +{ + m_recentFilesAction->saveEntries(config); + delete config; +} + +void Kig::setupActions() +{ + KStdAction::openNew(this, SLOT(fileNew()), actionCollection()); + KStdAction::open(this, SLOT(fileOpen()), actionCollection()); + KStdAction::quit(this, SLOT(close()), actionCollection()); + +#ifdef KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES + m_toolbarAction = KStdAction::showToolbar(this, SLOT(optionsShowToolbar()), actionCollection()); + m_statusbarAction = KStdAction::showStatusbar(this, SLOT(optionsShowStatusbar()), actionCollection()); +#else + createStandardStatusBarAction(); + setStandardToolBarMenuEnabled(true); +#endif + + // FIXME: this (recent files) should be app-wide, not specific to each window... + m_recentFilesAction = KStdAction::openRecent(this, SLOT(openURL(const KURL&)), actionCollection()); + m_recentFilesAction->loadEntries(config); + +#if KDE_IS_VERSION( 3, 2, 90 ) + KStdAction::keyBindings( guiFactory(), SLOT( configureShortcuts() ), actionCollection() ); +#else + KStdAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection()); +#endif + KStdAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection()); + + KStdAction::tipOfDay( this, SLOT( tipOfDay() ), actionCollection(), "help_tipofday" ); +} + +void Kig::saveProperties(KConfig* config) +{ + // the 'config' object points to the session managed + // config file. anything you write here will be available + // later when this app is restored + config->writePathEntry("fileName", m_part->url().path()); +} + +void Kig::readProperties(KConfig* config) +{ + // the 'config' object points to the session managed + // config file. this function is automatically called whenever + // the app is being restored. read in here whatever you wrote + // in 'saveProperties' + load ( KURL(config->readPathEntry("fileName"))); +} + +void Kig::load(const KURL& url) +{ + // we check for m_part not being 0, because in the case of us not + // finding our library, we would otherwise get a crash... + if ( m_part && m_part->openURL( url ) ) m_recentFilesAction->addURL( url ); +} + +void Kig::fileNew() +{ + // this slot is called whenever the File->New menu is selected, + // the New shortcut is pressed (usually CTRL+N) or the New toolbar + // button is clicked + + // create a new window if we aren't in the "initial state" ( see + // the KDE style guide on the file menu stuff...) + if ( ! m_part->url().isEmpty() || m_part->isModified() ) + (new Kig)->show(); +} + +void Kig::openURL(const KURL& url) +{ + // Called for opening a file by either the KRecentFilesAction or our + // own fileOpen() method. + // if we are in the "initial state", we open the url in this window: + if ( m_part->url().isEmpty() && ! m_part->isModified() ) + { + load( url ); + } + else + { + // otherwise we open it in a new window... + Kig* widget = new Kig; + widget->load(url); + widget->show(); + }; +} + +void Kig::optionsConfigureKeys() +{ +#if KDE_IS_VERSION( 3, 2, 90 ) + assert( false ); +#else + KKeyDialog dlg( true, this ); + dlg.insert( actionCollection() ); + dlg.insert( m_part->actionCollection() ); + (void) dlg.configure( true ); +#endif +} + +void Kig::optionsConfigureToolbars() +{ + saveMainWindowSettings(KGlobal::config(), "MainWindow"); + + // use the standard toolbar editor + KEditToolbar dlg(factory()); + connect(&dlg, SIGNAL(newToolbarConfig()), + this, SLOT(applyNewToolbarConfig())); + dlg.exec(); +} + +void Kig::applyNewToolbarConfig() +{ + applyMainWindowSettings(KGlobal::config(), "MainWindow"); +} + +bool Kig::queryClose() +{ + if (!m_part->isReadWrite() || !m_part->isModified()) return true; + switch( KMessageBox::warningYesNoCancel + ( + widget(), + i18n("Save changes to document %1?").arg(m_part->url().path()), + i18n("Save Changes?"),KStdGuiItem::save(),KStdGuiItem::discard() + )) + { + case KMessageBox::Yes: + if (m_part->save()) return true; + else return false; + break; + case KMessageBox::No: + return true; + break; + default: // cancel + return false; + break; + }; +} + +void Kig::dragEnterEvent(QDragEnterEvent* e) +{ + e->accept(KURLDrag::canDecode(e)); +} + +void Kig::dropEvent(QDropEvent* e) +{ + KURL::List urls; + if ( KURLDrag::decode (e, urls) ) + { + for (KURL::List::iterator u = urls.begin(); u != urls.end(); ++u) + { + Kig* k = new Kig; + k->show(); + k->load(*u); + }; + }; +} + +void Kig::fileOpen() +{ + QString formats = + i18n( "*.kig *.kigz *.kgeo *.seg|All Supported Files (*.kig *.kigz *.kgeo *.seg)\n" + "*.kig|Kig Documents (*.kig)\n" + "*.kigz|Compressed Kig Documents (*.kigz)\n" + "*.kgeo|KGeo Documents (*.kgeo)\n" + "*.seg|KSeg Documents (*.seg)\n" + "*.fgeo|Dr. Geo Documents (*.fgeo)\n" + "*.fig *.FIG|Cabri Documents (*.fig *.FIG)" ); + + // this slot is connected to the KStdAction::open action... + QString file_name = KFileDialog::getOpenFileName(":document", formats ); + + if (!file_name.isEmpty()) openURL(file_name); +} + +// ifdef's disabled, cause Qt moc doesn't handle ifdef's.. +// #ifdef KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES +void Kig::optionsShowToolbar() +{ +#ifdef KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES + if (m_toolbarAction->isChecked()) + toolBar()->show(); + else + toolBar()->hide(); +#else + assert( false ); +#endif +} + +void Kig::optionsShowStatusbar() +{ +#ifdef KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES + if (m_statusbarAction->isChecked()) + statusBar()->show(); + else + statusBar()->hide(); +#else + assert( false ); +#endif +} +// #endif + +void Kig::tipOfDay() { + KTipDialog::showTip( "kig/tips", true ); +} + +void Kig::startupTipOfDay() { + KTipDialog::showTip( "kig/tips" ); +} diff --git a/kig/kig/kig.desktop b/kig/kig/kig.desktop new file mode 100644 index 00000000..b2e11e40 --- /dev/null +++ b/kig/kig/kig.desktop @@ -0,0 +1,121 @@ +[Desktop Entry] +Name=Kig +Name[bn]=কিগ +Name[hi]=केआईजी +Name[ne]=किग +Name[pa]=ਕਿਗ +Name[ta]=கிக் +GenericName=Interactive Geometry +GenericName[af]=Interaktiewe Meetkunde +GenericName[be]=Інтэрактыўная геаметрыя +GenericName[bg]=Интерактивна геометрия +GenericName[bn]=ইন্টারঅ্যাকটিভ জ্যামিতি +GenericName[bs]=Interaktivna geometrija +GenericName[ca]=Geometria interactiva +GenericName[cs]=Interaktivní geometrie +GenericName[csb]=Interaktiwnô geòmetrëjô +GenericName[cy]=Geometreg Rhyngweithiol +GenericName[da]=Interaktiv geometri +GenericName[de]=Interaktive Geometrie +GenericName[el]=Aλληλεπιδραστική γεωμετρία +GenericName[eo]=Interaga geometrios +GenericName[es]=Geometría interactiva +GenericName[et]=Interaktiivne geomeetria +GenericName[eu]=Geometria interaktiboa +GenericName[fa]=هندسۀ تعاملی +GenericName[fi]=Interaktiivinen Geometria +GenericName[fr]=Géométrie interactive +GenericName[ga]=Céimseata Idirghníomhach +GenericName[gl]=Xeometría Interactiva +GenericName[he]=גאומטריה אינטראקטיבית +GenericName[hi]=इंटरएक्टिव ज्यॉमिती +GenericName[hr]=Interaktivna geometrija +GenericName[hu]=Interaktív geometria +GenericName[is]=Gagnvirk rúmfræði +GenericName[it]=Geometria interattiva +GenericName[ja]=幾何学との対話 +GenericName[ka]=ინტერაქტიური გეომეტრია +GenericName[km]=ធរណីមាត្រអន្តរកម្ម +GenericName[lt]=Interaktyvi geometrija +GenericName[ms]=Geometri Interaktif +GenericName[nb]=Interaktiv geometri +GenericName[nds]=Wesselwarken Geometrie +GenericName[ne]=अन्तर्क्रियात्मक भूगोल +GenericName[nl]=Interactieve geometry +GenericName[nn]=Interaktiv geometri +GenericName[pa]=ਦਿਲ-ਖਿਚਵੀਂ ਜੁਮੈਟਰੀ +GenericName[pl]=Interaktywna geometria +GenericName[pt]=Geometria Interactiva +GenericName[pt_BR]=Geometria interativa +GenericName[ru]=Интерактивная геометрия +GenericName[sk]=Interaktívna geometria +GenericName[sl]=Interaktivna geometrija +GenericName[sr]=Интерактивна геометрија +GenericName[sr@Latn]=Interaktivna geometrija +GenericName[sv]=Interaktiv geometri +GenericName[ta]= ஊடாடும் வடிவியல் +GenericName[tg]=Геометрияи интерактивӣ +GenericName[tr]=Etkileşimli Geometri +GenericName[uk]=Інтерактивна геометрія +GenericName[ven]=Geometry yau shumea nayo +GenericName[vi]=Hình học Tương tác +GenericName[xh]=Umyili Wesiboniso Esingaphakathi +GenericName[zh_CN]=交互几何 +GenericName[zh_TW]=交互式幾何作圖 +GenericName[zu]=Ukubekeka Kwebalazwe Kokukhulumisanayo +Comment=Explore Geometric Constructions +Comment[be]=Вывучэнне геаметрычных фігур +Comment[bg]=Геометрични конструкции +Comment[bn]=জ্যামিতি ছবি আঁকা চর্চা করুন +Comment[bs]=Istražite geometrijske konstrukcije +Comment[ca]=Explora construccions geomètriques +Comment[cs]=Objevujte geometrické konstrukce +Comment[csb]=Exploatëjë geòmetriczne kònstrukcëjë +Comment[da]=Udforsk geometriske konstruktioner +Comment[de]=Geometrische Konstruktionen untersuchen +Comment[el]=Εξερεύνηση γεωμετρικών κατασκευών +Comment[eo]=Explorado de geometriaj konstruaĵoj +Comment[es]=Exploración de construcciones geométricas +Comment[et]=Geomeetriliste kujundite tundmaõppimine +Comment[eu]=Arakatu geometria egiturak +Comment[fa]=کاوش ساختارهای هندسی +Comment[fi]=Tutki geometrisia rakenteita +Comment[fr]=Explorer les constructions géométriques +Comment[ga]=Taiscéal Tógálacha Céimseatúla +Comment[gl]=Explore as Figuras Xeométricas +Comment[he]=חקור מבנים גאומטריים +Comment[hr]=Upoznajte geometrijske konstrukcije +Comment[hu]=Geometriai oktatóprogram +Comment[is]=Kanna rúmfræðilega byggingu forma +Comment[it]=Esplora le costruzioni geometriche +Comment[ja]=幾何学との対話 +Comment[ka]=გეომეტრიულ ფიგურათა შესწავლა +Comment[km]=រុករកសំណង់ធរណីមាត្រ +Comment[lt]=Geometrinių konstrukcijų tyrinėjimas +Comment[ms]=Jelahan Pembinaan Geometrik +Comment[nb]=Utforsk geometriske konstruksjoner +Comment[nds]=Geometersch Konstrukschonen bekieken +Comment[ne]=भूगोल बनावट अन्वेषण गर्नुहोस् +Comment[nl]=Ruimtelijke constructies verkennen +Comment[nn]=Utforsk geometriske konstruksjonar +Comment[pl]=Zabawa konstrukcjami geometrycznymi +Comment[pt]=Explorar Construções Geométricas +Comment[pt_BR]=Explore construções geométricas +Comment[ru]=Работа с геометрическими построениями +Comment[sk]=Prieskum geometrických konštrukcií +Comment[sl]=Raziskovanje geometrijskih konstrukcij +Comment[sr]=Истражујте геометријске конструкције +Comment[sr@Latn]=Istražujte geometrijske konstrukcije +Comment[sv]=Utforska geometriska konstruktioner +Comment[tr]=Geometik Şekilleri Keşfedin +Comment[uk]=Дослідження геометричних конструкцій +Comment[vi]=Khám phá các phép Dụng Hình học +Comment[zh_CN]=探索几何构造的世界 +Comment[zh_TW]=作出幾何圖形 +Exec=kig %i %m -caption "%c" +MimeType=application/x-kig;application/x-kgeo; +Icon=kig +Type=Application +DocPath=kig/index.html +Terminal=false +Categories=Qt;KDE;Education;Math; diff --git a/kig/kig/kig.h b/kig/kig/kig.h new file mode 100644 index 00000000..d6ad9fea --- /dev/null +++ b/kig/kig/kig.h @@ -0,0 +1,148 @@ +// This file is part of Kig, a KDE program for Interactive Geometry... +// Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + +// 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. + +// 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. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#ifndef KIG_KIG_H +#define KIG_KIG_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <kdeversion.h> + +#ifdef KDE_IS_VERSION +#if KDE_IS_VERSION( 3, 1, 90 ) +#undef KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES +#else +#define KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES +#endif +#else +#define KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES +#endif + +#include <kapplication.h> +#include <kparts/mainwindow.h> +#include <dcopclient.h> + +class KToggleAction; +class KRecentFilesAction; + +/** + * This is the application "Shell". It has a menubar, toolbar, and + * statusbar but relies on the "Part" to do all the real work. + */ +class Kig : public KParts::MainWindow +{ + Q_OBJECT + public: + /** + * Default Constructor + */ + Kig(); + + /** + * Default Destructor + */ + virtual ~Kig(); + + public slots: + /** + * Open file in this window + * \param file file to open + */ + void load (const KURL& file); + + /** + * this opens the file specified in \p s in a new window + * + * \param s the url of the file to open + */ + void openURL (const QString& s) { openURL(KURL(s)); } + void openURL (const KURL& s); + + protected: + + /** + * The user started dragging something onto us... + * + * \param e + */ + void dragEnterEvent(QDragEnterEvent* e); + + /** + * The user dropped something onto us... + * + * \param e + */ + void dropEvent (QDropEvent* e); + + /** + * this is called by the framework before closing the window, to + * allow the user to save his changes... returning false cancels the + * close request... + */ + bool queryClose(); + + /** + * This method is called when it is time for the app to save its + * properties for session management purposes. + */ + void saveProperties(KConfig *); + + /** + * This method is called when this app is restored. The KConfig + * object points to the session management config file that was saved + * with \ref saveProperties + */ + void readProperties(KConfig *); + + private slots: + void fileNew(); + void fileOpen(); + // Qt moc doesn't handle ifdef's, so i'm disabling it.. +// #ifdef KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES + void optionsShowToolbar(); + void optionsShowStatusbar(); +// #endif +// #if KDE_IS_VERSION( 3, 2, 90 ) + void optionsConfigureKeys(); +// #endif + void optionsConfigureToolbars(); + + void applyNewToolbarConfig(); + + void tipOfDay(); + void startupTipOfDay(); + + private: + void setupActions(); + + KParts::ReadWritePart *m_part; + +//#ifdef KIG_DONT_USE_NEW_KMAINWINDOW_FEATURES + KToggleAction *m_toolbarAction; + KToggleAction *m_statusbarAction; +//#endif + KRecentFilesAction *m_recentFilesAction; + + KConfig* config; + + static bool kimageioRegistered; +}; + +#endif // KIG_KIG_H diff --git a/kig/kig/kig_commands.cpp b/kig/kig/kig_commands.cpp new file mode 100644 index 00000000..b9846fa6 --- /dev/null +++ b/kig/kig/kig_commands.cpp @@ -0,0 +1,398 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + +#include "kig_commands.h" +#include "kig_commands.moc" + +#include "kig_part.h" +#include "kig_document.h" +#include "kig_view.h" + +#include "../modes/mode.h" +#include "../objects/object_imp.h" +#include "../objects/object_drawer.h" +#include "../misc/calcpaths.h" +#include "../misc/coordinate_system.h" + +#include <vector> + +using std::vector; +using std::max; +using std::min; + +class KigCommand::Private +{ +public: + Private( KigPart& d ) : doc( d ) {} + KigPart& doc; + vector<KigCommandTask*> tasks; +}; + +KigCommand::KigCommand( KigPart& doc, const QString& name ) + : KNamedCommand(name), d( new Private( doc ) ) +{ +} + +KigCommand::~KigCommand() +{ + for ( uint i = 0; i < d->tasks.size(); ++i ) + delete d->tasks[i]; + delete d; +} + +void KigCommand::execute() +{ + for ( uint i = 0; i < d->tasks.size(); ++i ) + d->tasks[i]->execute( d->doc ); + d->doc.redrawScreen(); +} + +void KigCommand::unexecute() +{ + for ( uint i = 0; i < d->tasks.size(); ++i ) + d->tasks[i]->unexecute( d->doc ); + d->doc.redrawScreen(); +} + +void KigCommand::addTask( KigCommandTask* t ) +{ + d->tasks.push_back( t ); +} + +KigCommand* KigCommand::removeCommand( KigPart& doc, ObjectHolder* o ) +{ + std::vector<ObjectHolder*> os; + os.push_back( o ); + return removeCommand( doc, os ); +} + +KigCommand* KigCommand::addCommand( KigPart& doc, ObjectHolder* o ) +{ + std::vector<ObjectHolder*> os; + os.push_back( o ); + return addCommand( doc, os ); +} + +KigCommand* KigCommand::removeCommand( KigPart& doc, const std::vector<ObjectHolder*>& os ) +{ + assert( os.size() > 0 ); + QString text; + if ( os.size() == 1 ) + text = os.back()->imp()->type()->removeAStatement(); + else + text = i18n( "Remove %1 Objects" ).arg( os.size() ); + KigCommand* ret = new KigCommand( doc, text ); + ret->addTask( new RemoveObjectsTask( os ) ); + return ret; +} + +KigCommand* KigCommand::addCommand( KigPart& doc, const std::vector<ObjectHolder*>& os ) +{ + QString text; + if ( os.size() == 1 ) + text = os.back()->imp()->type()->addAStatement(); + else + text = i18n( "Add %1 Objects" ).arg( os.size() ); + KigCommand* ret = new KigCommand( doc, text ); + ret->addTask( new AddObjectsTask( os ) ); + return ret; +} + +KigCommand* KigCommand::changeCoordSystemCommand( KigPart& doc, CoordinateSystem* s ) +{ + QString text = CoordinateSystemFactory::setCoordinateSystemStatement( s->id() ); + KigCommand* ret = new KigCommand( doc, text ); + ret->addTask( new ChangeCoordSystemTask( s ) ); + return ret; +} + +KigCommandTask::KigCommandTask() +{ +} + +KigCommandTask::~KigCommandTask() +{ +} + +AddObjectsTask::AddObjectsTask( const std::vector<ObjectHolder*>& os) + : KigCommandTask(), undone( true ), mobjs( os ) +{ +} + +void AddObjectsTask::execute( KigPart& doc ) +{ + doc._addObjects( mobjs ); + undone = false; +} + +void AddObjectsTask::unexecute( KigPart& doc ) +{ + doc._delObjects( mobjs ); + undone = true; +} + +AddObjectsTask::~AddObjectsTask() +{ + if ( undone ) + for ( std::vector<ObjectHolder*>::iterator i = mobjs.begin(); + i != mobjs.end(); ++i ) + delete *i; +} + +RemoveObjectsTask::RemoveObjectsTask( const std::vector<ObjectHolder*>& os ) + : AddObjectsTask( os ) +{ + undone = false; +} + +void RemoveObjectsTask::execute( KigPart& doc ) +{ + AddObjectsTask::unexecute( doc ); +} + +void RemoveObjectsTask::unexecute( KigPart& doc ) +{ + AddObjectsTask::execute( doc ); +} + +ChangeObjectConstCalcerTask::ChangeObjectConstCalcerTask( ObjectConstCalcer* calcer, ObjectImp* newimp ) + : KigCommandTask(), mcalcer( calcer ), mnewimp( newimp ) +{ +} + +void ChangeObjectConstCalcerTask::execute( KigPart& doc ) +{ + mnewimp = mcalcer->switchImp( mnewimp ); + + std::set<ObjectCalcer*> allchildren = getAllChildren( mcalcer.get() ); + std::vector<ObjectCalcer*> allchildrenvect( allchildren.begin(), allchildren.end() ); + allchildrenvect = calcPath( allchildrenvect ); + for ( std::vector<ObjectCalcer*>::iterator i = allchildrenvect.begin(); + i != allchildrenvect.end(); ++i ) + ( *i )->calc( doc.document() ); +} + +void ChangeObjectConstCalcerTask::unexecute( KigPart& doc ) +{ + execute( doc ); +} + +struct MoveDataStruct +{ + ObjectConstCalcer* o; + ObjectImp* oldimp; + MoveDataStruct( ObjectConstCalcer* io, ObjectImp* oi ) + : o( io ), oldimp( oi ) { } +}; + +class MonitorDataObjects::Private +{ +public: + vector<MoveDataStruct> movedata; +}; + +MonitorDataObjects::MonitorDataObjects( const std::vector<ObjectCalcer*>& objs ) + : d( new Private ) +{ + monitor( objs ); +} + +void MonitorDataObjects::monitor( const std::vector<ObjectCalcer*>& objs ) +{ + for ( std::vector<ObjectCalcer*>::const_iterator i = objs.begin(); i != objs.end(); ++i ) + if ( dynamic_cast<ObjectConstCalcer*>( *i ) ) + { + MoveDataStruct n( static_cast<ObjectConstCalcer*>( *i ), (*i)->imp()->copy() ); + d->movedata.push_back( n ); + }; +} + +void MonitorDataObjects::finish( KigCommand* comm ) +{ + for ( uint i = 0; i < d->movedata.size(); ++i ) + { + ObjectConstCalcer* o = d->movedata[i].o; + if ( ! d->movedata[i].oldimp->equals( *o->imp() ) ) + { + ObjectImp* newimp = o->switchImp( d->movedata[i].oldimp ); + comm->addTask( new ChangeObjectConstCalcerTask( o, newimp ) ); + } + else + delete d->movedata[i].oldimp; + }; + d->movedata.clear(); +} + +MonitorDataObjects::~MonitorDataObjects() +{ + assert( d->movedata.empty() ); + delete d; +} + +ChangeCoordSystemTask::ChangeCoordSystemTask( CoordinateSystem* s ) + : KigCommandTask(), mcs( s ) +{ +} + +void ChangeCoordSystemTask::execute( KigPart& doc ) +{ + mcs = doc.document().switchCoordinateSystem( mcs ); + std::vector<ObjectCalcer*> calcpath = calcPath( getAllCalcers( doc.document().objects() ) ); + for ( std::vector<ObjectCalcer*>::iterator i = calcpath.begin(); i != calcpath.end(); ++i ) + ( *i )->calc( doc.document() ); + doc.coordSystemChanged( doc.document().coordinateSystem().id() ); +} + +void ChangeCoordSystemTask::unexecute( KigPart& doc ) +{ + execute( doc ); +} + +ChangeCoordSystemTask::~ChangeCoordSystemTask() +{ + delete mcs; +} + +class ChangeParentsAndTypeTask::Private +{ +public: + ObjectTypeCalcer* o; + std::vector<ObjectCalcer::shared_ptr> newparents; + const ObjectType* newtype; +}; + +ChangeParentsAndTypeTask::~ChangeParentsAndTypeTask() +{ + delete d; +} + +ChangeParentsAndTypeTask::ChangeParentsAndTypeTask( + ObjectTypeCalcer* o, const std::vector<ObjectCalcer*>& newparents, + const ObjectType* newtype ) + : KigCommandTask(), d( new Private ) +{ + d->o = o; + std::copy( newparents.begin(), newparents.end(), + std::back_inserter( d->newparents ) ); + d->newtype = newtype; +} + +void ChangeParentsAndTypeTask::execute( KigPart& doc ) +{ + const ObjectType* oldtype = d->o->type(); + d->o->setType( d->newtype ); + d->newtype = oldtype; + + std::vector<ObjectCalcer*> oldparentso = d->o->parents(); + std::vector<ObjectCalcer::shared_ptr> oldparents( + oldparentso.begin(), oldparentso.end() ); + std::vector<ObjectCalcer*> newparents; + for ( std::vector<ObjectCalcer::shared_ptr>::iterator i = d->newparents.begin(); + i != d->newparents.end(); ++i ) + newparents.push_back( i->get() ); + d->o->setParents( newparents ); + d->newparents = oldparents; + + for ( std::vector<ObjectCalcer*>::iterator i = newparents.begin(); i != newparents.end(); ++i ) + ( *i )->calc( doc.document() ); + d->o->calc( doc.document() ); + std::set<ObjectCalcer*> allchildren = getAllChildren( d->o ); + std::vector<ObjectCalcer*> allchildrenvect( allchildren.begin(), allchildren.end() ); + allchildrenvect = calcPath( allchildrenvect ); + for ( std::vector<ObjectCalcer*>::iterator i = allchildrenvect.begin(); + i != allchildrenvect.end(); ++i ) + ( *i )->calc( doc.document() ); +} + +void ChangeParentsAndTypeTask::unexecute( KigPart& doc ) +{ + execute( doc ); +} + +class KigViewShownRectChangeTask::Private +{ +public: + Private( KigWidget& view, const Rect& r ) : v( view ), rect( r ) { } + KigWidget& v; + Rect rect; +}; + +KigViewShownRectChangeTask::KigViewShownRectChangeTask( + KigWidget& v, const Rect& newrect ) + : KigCommandTask() +{ + d = new Private( v, newrect ); +} + +KigViewShownRectChangeTask::~KigViewShownRectChangeTask() +{ + delete d; +} + +void KigViewShownRectChangeTask::execute( KigPart& doc ) +{ + Rect oldrect = d->v.showingRect(); + d->v.setShowingRect( d->rect ); + doc.mode()->redrawScreen( &d->v ); + d->v.updateScrollBars(); + d->rect = oldrect; +} + +void KigViewShownRectChangeTask::unexecute( KigPart& doc ) +{ + execute( doc ); +} + +ChangeObjectDrawerTask::~ChangeObjectDrawerTask() +{ + delete mnewdrawer; +} + +ChangeObjectDrawerTask::ChangeObjectDrawerTask( + ObjectHolder* holder, ObjectDrawer* newdrawer ) + : KigCommandTask(), mholder( holder ), mnewdrawer( newdrawer ) +{ +} + +void ChangeObjectDrawerTask::execute( KigPart& ) +{ + mnewdrawer = mholder->switchDrawer( mnewdrawer ); +} + +void ChangeObjectDrawerTask::unexecute( KigPart& doc ) +{ + execute( doc ); +} + +MonitorDataObjects::MonitorDataObjects( ObjectCalcer* c ) + : d( new Private ) +{ + if ( dynamic_cast<ObjectConstCalcer*>( c ) ) + { + MoveDataStruct n( static_cast<ObjectConstCalcer*>( c ), c->imp()->copy() ); + d->movedata.push_back( n ); + }; +} + +ChangeObjectConstCalcerTask::~ChangeObjectConstCalcerTask() +{ + delete mnewimp; +} + diff --git a/kig/kig/kig_commands.h b/kig/kig/kig_commands.h new file mode 100644 index 00000000..8e4fd044 --- /dev/null +++ b/kig/kig/kig_commands.h @@ -0,0 +1,217 @@ +/* + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +*/ + + +#ifndef KIG_COMMANDS_H +#define KIG_COMMANDS_H + +#include <kcommand.h> +#include <klocale.h> +#include <kdebug.h> + +#include "../objects/object_holder.h" + +class KigDocument; +class KigPart; +class CoordinateSystem; + +class KigCommandTask; +class KigWidget; +class Rect; + +/** + * a KigCommand represents almost every action performed in Kig. + * Used mainly in the Undo/Redo stuff... + */ +class KigCommand + : public QObject, public KNamedCommand +{ + Q_OBJECT + class Private; + Private* d; +public: + KigCommand( KigPart& inDoc, const QString& name ); + ~KigCommand(); + + /** + * To avoid confusion, this doesn't add a command to anything, this + * creates an AddCommand ;) + */ + static KigCommand* addCommand( KigPart& doc, const std::vector<ObjectHolder*>& os ); + static KigCommand* addCommand( KigPart& doc, ObjectHolder* os ); + /** + * make sure that when you delete something, you are also deleting + * its parents. This class assumes you've done that. + * \ref KigDocument::delObjects() takes care of this for you. + */ + static KigCommand* removeCommand( KigPart& doc, const std::vector<ObjectHolder*>& os ); + static KigCommand* removeCommand( KigPart& doc, ObjectHolder* o ); + + static KigCommand* changeCoordSystemCommand( KigPart& doc, CoordinateSystem* s ); + + void addTask( KigCommandTask* ); + + void execute(); + void unexecute(); +}; + +class KigCommandTask +{ +public: + KigCommandTask(); + virtual ~KigCommandTask(); + + virtual void execute( KigPart& doc ) = 0; + virtual void unexecute( KigPart& doc ) = 0; +}; + +class AddObjectsTask + : public KigCommandTask +{ +public: + AddObjectsTask( const std::vector<ObjectHolder*>& os); + ~AddObjectsTask (); + void execute( KigPart& doc ); + void unexecute( KigPart& doc ); +protected: + bool undone; + + std::vector<ObjectHolder*> mobjs; +}; + +class RemoveObjectsTask + : public AddObjectsTask +{ +public: + RemoveObjectsTask( const std::vector<ObjectHolder*>& os ); + void execute( KigPart& ); + void unexecute( KigPart& ); +}; + +class ChangeObjectConstCalcerTask + : public KigCommandTask +{ +public: + ChangeObjectConstCalcerTask( ObjectConstCalcer* calcer, ObjectImp* newimp ); + ~ChangeObjectConstCalcerTask(); + + void execute( KigPart& ); + void unexecute( KigPart& ); +protected: + ObjectConstCalcer::shared_ptr mcalcer; + ObjectImp* mnewimp; +}; + +/** + * this class monitors a set of DataObjects for changes and returns an + * appropriate ChangeObjectImpsCommand if necessary.. + * E.g. MovingMode wants to move certain objects, so it monitors all + * the parents of the explicitly moving objects: + * \code + * MonitorDataObjects mon( getAllParents( emo ) ); + * \endcode + * It then moves them around, and when it is finished, it asks to add + * the KigCommandTasks to a KigCommand, and applies that.. + * \code + * KigCommand* comm = new KigCommand( doc, i18n( "Move Stuff" ) ); + * mon.finish( comm ); + * \endcode + */ +class MonitorDataObjects +{ + class Private; + Private* d; +public: + /** + * all the DataObjects in \p objs will be watched.. + */ + MonitorDataObjects( const std::vector<ObjectCalcer*>& objs ); + MonitorDataObjects( ObjectCalcer* c ); + ~MonitorDataObjects(); + + /** + * add \p objs to the list of objs to be watched, and save their + * current imp's.. + */ + void monitor( const std::vector<ObjectCalcer*>& objs ); + + /** + * add the generated KigCommandTasks to the command \p comm .. + * monitoring stops after this is called.. + */ + void finish( KigCommand* comm ); +}; + +class ChangeCoordSystemTask + : public KigCommandTask +{ + CoordinateSystem* mcs; +public: + /** + * a command that changes the coordinate-system to \p s .. + */ + ChangeCoordSystemTask( CoordinateSystem* s ); + ~ChangeCoordSystemTask(); + + void execute( KigPart& doc ); + void unexecute( KigPart& doc ); +}; + +class ChangeParentsAndTypeTask + : public KigCommandTask +{ + class Private; + Private* d; +public: + ChangeParentsAndTypeTask( ObjectTypeCalcer* o, const std::vector<ObjectCalcer*>& newparents, + const ObjectType* newtype ); + ~ChangeParentsAndTypeTask(); + + void execute( KigPart& doc ); + void unexecute( KigPart& doc ); +}; + +class KigViewShownRectChangeTask + : public KigCommandTask +{ + class Private; + Private* d; +public: + KigViewShownRectChangeTask( KigWidget& v, const Rect& newrect ); + ~KigViewShownRectChangeTask(); + + void execute( KigPart& doc ); + void unexecute( KigPart& doc ); +}; + +class ChangeObjectDrawerTask + : public KigCommandTask +{ + ObjectHolder* mholder; + ObjectDrawer* mnewdrawer; +public: + ChangeObjectDrawerTask( ObjectHolder* holder, ObjectDrawer* newdrawer ); + ~ChangeObjectDrawerTask(); + + void execute( KigPart& doc ); + void unexecute( KigPart& doc ); +}; + +#endif diff --git a/kig/kig/kig_document.cc b/kig/kig/kig_document.cc new file mode 100644 index 00000000..884b41c5 --- /dev/null +++ b/kig/kig/kig_document.cc @@ -0,0 +1,200 @@ +// Copyright (C) 2004 Dominique Devriese <devriese@kde.org> + +// 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. + +// 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. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#include "kig_document.h" + +#include "../objects/object_calcer.h" +#include "../objects/object_holder.h" +#include "../objects/point_imp.h" +#include "../objects/polygon_imp.h" +#include "../misc/coordinate_system.h" +#include "../misc/rect.h" + +#include <assert.h> + +KigDocument::KigDocument( std::set<ObjectHolder*> objects, CoordinateSystem* coordsystem, + bool showgrid, bool showaxes, bool nv ) + : mobjects( objects ), mcoordsystem( coordsystem ), mshowgrid( showgrid ), + mshowaxes( showaxes ), mnightvision( nv ) +{ +} + +const CoordinateSystem& KigDocument::coordinateSystem() const +{ + assert( mcoordsystem ); + return *mcoordsystem; +} + +const std::vector<ObjectHolder*> KigDocument::objects() const +{ + return std::vector<ObjectHolder*>( mobjects.begin(), mobjects.end() ); +} + +const std::set<ObjectHolder*>& KigDocument::objectsSet() const +{ + return mobjects; +} + +void KigDocument::setCoordinateSystem( CoordinateSystem* s ) +{ + delete switchCoordinateSystem( s ); +} + +CoordinateSystem* KigDocument::switchCoordinateSystem( CoordinateSystem* s ) +{ + CoordinateSystem* ret = mcoordsystem; + mcoordsystem = s; + return ret; +} + +std::vector<ObjectHolder*> KigDocument::whatAmIOn( const Coordinate& p, const KigWidget& w ) const +{ + std::vector<ObjectHolder*> ret; + std::vector<ObjectHolder*> curves; + std::vector<ObjectHolder*> fatobjects; + for ( std::set<ObjectHolder*>::const_iterator i = mobjects.begin(); + i != mobjects.end(); ++i ) + { + if(!(*i)->contains(p, w, mnightvision)) continue; + if ( (*i)->imp()->inherits( PointImp::stype() ) ) ret.push_back( *i ); + else + if ( !(*i)->imp()->inherits( PolygonImp::stype() ) ) curves.push_back( *i ); + else fatobjects.push_back( *i ); + }; + std::copy( curves.begin(), curves.end(), std::back_inserter( ret ) ); + std::copy( fatobjects.begin(), fatobjects.end(), std::back_inserter( ret ) ); + return ret; +} + +std::vector<ObjectHolder*> KigDocument::whatIsInHere( const Rect& p, const KigWidget& w ) +{ + std::vector<ObjectHolder*> ret; + std::vector<ObjectHolder*> nonpoints; + for ( std::set<ObjectHolder*>::const_iterator i = mobjects.begin(); + i != mobjects.end(); ++i ) + { + if(! (*i)->inRect( p, w ) ) continue; + if ( (*i)->imp()->inherits( PointImp::stype() ) ) ret.push_back( *i ); + else nonpoints.push_back( *i ); + }; + std::copy( nonpoints.begin(), nonpoints.end(), std::back_inserter( ret ) ); + return ret; +} + +Rect KigDocument::suggestedRect() const +{ + bool rectInited = false; + Rect r(0.,0.,0.,0.); + for ( std::set<ObjectHolder*>::const_iterator i = mobjects.begin(); + i != mobjects.end(); ++i ) + { + if ( (*i)->shown() ) + { + Rect cr = (*i)->imp()->surroundingRect(); + if ( ! cr.valid() ) continue; + if( !rectInited ) + { + r = cr; + rectInited = true; + } + else + r.eat( cr ); + }; + }; + + if ( ! rectInited ) + return Rect( -5.5, -5.5, 11., 11. ); + r.setContains( Coordinate( 0, 0 ) ); + if( r.width() == 0 ) r.setWidth( 1 ); + if( r.height() == 0 ) r.setHeight( 1 ); + Coordinate center = r.center(); + r *= 2; + r.setCenter(center); + return r; +} + +void KigDocument::addObject( ObjectHolder* o ) +{ + mobjects.insert( o ); +} + +void KigDocument::addObjects( const std::vector<ObjectHolder*>& os ) +{ + for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); + i != os.end(); ++i ) + ( *i )->calc( *this ); + std::copy( os.begin(), os.end(), std::inserter( mobjects, mobjects.begin() ) ); +} + +void KigDocument::delObject( ObjectHolder* o ) +{ + mobjects.erase( o ); +} + +void KigDocument::delObjects( const std::vector<ObjectHolder*>& os ) +{ + for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); + i != os.end(); ++i ) + mobjects.erase( *i ); +} + +KigDocument::KigDocument() + : mcoordsystem( new EuclideanCoords ) +{ + mshowgrid = true; + mshowaxes = true; + mnightvision = false; +} + +KigDocument::~KigDocument() +{ + typedef std::set<ObjectHolder*> s; + for ( s::iterator i = mobjects.begin(); i != mobjects.end(); ++i ) { + delete *i; + } + delete mcoordsystem; +} + +void KigDocument::setGrid( bool showgrid ) +{ + mshowgrid = showgrid; +} + +const bool KigDocument::grid() const +{ + return mshowgrid; +} + +void KigDocument::setAxes( bool showaxes ) +{ + mshowaxes = showaxes; +} + +void KigDocument::setNightVision( bool nv ) +{ + mnightvision = nv; +} + +const bool KigDocument::axes() const +{ + return mshowaxes; +} + +const bool KigDocument::getNightVision() const +{ + return mnightvision; +} diff --git a/kig/kig/kig_document.h b/kig/kig/kig_document.h new file mode 100644 index 00000000..6bcdb623 --- /dev/null +++ b/kig/kig/kig_document.h @@ -0,0 +1,137 @@ +// Copyright (C) 2004 Dominique Devriese <devriese@kde.org> + +// 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. + +// 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. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301, USA. + +#ifndef KIG_KIG_KIG_DOCUMENT_H +#define KIG_KIG_KIG_DOCUMENT_H + +#include <set> +#include <vector> + +class Coordinate; +class CoordinateSystem; +class KigWidget; +class ObjectHolder; +class Rect; + +/** + * KigDocument is the class holding the real data in a Kig document. + * It owns a set of Objects, and a CoordinateSystem, which comprise + * the entire content of a Kig document. + */ +class KigDocument { + /** + * Here we keep the objects in the document. These are only the + * objects that the user is aware of. Other objects exist as well, + * but there's no ObjectHolder for them, and they only exist because + * some other ObjectCalcer has them as its ancestor. + */ + std::set<ObjectHolder*> mobjects; + + /** + * The CoordinateSystem as the user sees it: this has little to do + * with the internal coordinates of the objects... It really serves + * to translate user coordinates from and to internal coordinates. + */ + CoordinateSystem* mcoordsystem; + /** + * Whether to show the grid. + */ + bool mshowgrid; + /** + * Whether to show the axes. + */ + bool mshowaxes; + /** + * Whether to enable visibility of hidden objects. + */ + bool mnightvision; +public: + KigDocument(); + KigDocument( std::set<ObjectHolder*> objects, CoordinateSystem* coordsystem, + bool showgrid = true, bool showaxes = true, bool nv = false ); + ~KigDocument(); + + const CoordinateSystem& coordinateSystem() const; + const bool grid() const; + const bool axes() const; + const bool getNightVision() const; + /** + * Get a hold of the objects of this KigDocument. + */ + const std::vector<ObjectHolder*> objects() const; + const std::set<ObjectHolder*>& objectsSet() const; + + /** + * sets the coordinate system to \p s , and returns the old one.. + */ + CoordinateSystem* switchCoordinateSystem( CoordinateSystem* s ); + + /** + * sets the coordinate system to \p s , and deletes the old one.. + */ + void setCoordinateSystem( CoordinateSystem* s ); + + /** + * set to show/hide the grid. + */ + void setGrid( bool showgrid ); + + /** + * set to show/hide the grid. + */ + void setAxes( bool showaxes ); + + /** + * set to enable/disable night-vision (visibility of hidden objects) + */ + void setNightVision( bool nv ); + + /** + * Return a vector of objects that contain the given point. + */ + std::vector<ObjectHolder*> whatAmIOn( const Coordinate& p, const KigWidget& w ) const; + + /** + * Return a vector of objects that are in the given Rect. + */ + std::vector<ObjectHolder*> whatIsInHere( const Rect& p, const KigWidget& ); + + /** + * Return a rect containing most of the objects, which would be a + * fine suggestion to map to the widget... + */ + Rect suggestedRect() const; + + /** + * Add the objects \p o to the document. + */ + void addObject( ObjectHolder* oObject ); + /** + * Add the objects \p os to the document. + */ + void addObjects( const std::vector<ObjectHolder*>& os); + /** + * Remove the object \p o from the document. + */ + void delObject( ObjectHolder* o ); + /** + * Remove the objects \p os from the document. + */ + void delObjects( const std::vector<ObjectHolder*>& os ); +}; + +#endif diff --git a/kig/kig/kig_iface.cpp b/kig/kig/kig_iface.cpp new file mode 100644 index 00000000..1f666a74 --- /dev/null +++ b/kig/kig/kig_iface.cpp @@ -0,0 +1,31 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + + +#include "kig_iface.h" + +KigIface::KigIface() + : DCOPObject("KigIface") +{ +} + +KigIface::~KigIface() +{ +} diff --git a/kig/kig/kig_iface.h b/kig/kig/kig_iface.h new file mode 100644 index 00000000..d3f74e19 --- /dev/null +++ b/kig/kig/kig_iface.h @@ -0,0 +1,37 @@ +/* + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +*/ + + +#ifndef KIG_IFACE_H +#define KIG_IFACE_H + +#include <dcopobject.h> + +class KigIface : virtual public DCOPObject +{ + K_DCOP +public: + KigIface(); + ~KigIface(); +k_dcop: + virtual void openURL(const QString& s) = 0; +}; + +#endif diff --git a/kig/kig/kig_part.cpp b/kig/kig/kig_part.cpp new file mode 100644 index 00000000..163f5429 --- /dev/null +++ b/kig/kig/kig_part.cpp @@ -0,0 +1,1041 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + +#include "kig_part.h" +#include "kig_part.moc" + +#include "aboutdata.h" +#include "kig_commands.h" +#include "kig_document.h" +#include "kig_view.h" + +#include "../filters/exporter.h" +#include "../filters/filter.h" +#include "../misc/builtin_stuff.h" +#include "../misc/calcpaths.h" +#include "../misc/coordinate_system.h" +#include "../misc/guiaction.h" +#include "../misc/kigpainter.h" +#include "../misc/lists.h" +#include "../misc/object_constructor.h" +#include "../misc/screeninfo.h" +#include "../modes/normal.h" +#include "../objects/object_drawer.h" +#include "../objects/point_imp.h" + +#include <algorithm> +#include <functional> + +#include <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kfiledialog.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <klocale.h> +#include <kmainwindow.h> +#include <kmessagebox.h> +#include <kmimetype.h> +#include <kprinter.h> +#include <kstandarddirs.h> +#include <kstdaction.h> +#include <ktoolbar.h> +#include <kparts/genericfactory.h> +#include <kdeprint/kprintdialogpage.h> + +#include <qcheckbox.h> +#include <qfile.h> +#include <qlayout.h> +#include <qpaintdevicemetrics.h> +#include <qsizepolicy.h> +#include <qtimer.h> +#if QT_VERSION >= 0x030100 +#include <qeventloop.h> +#endif + +using namespace std; + +static const QString typesFile = "macros.kigt"; + +// export this library... +typedef KParts::GenericFactory<KigPart> KigPartFactory; +K_EXPORT_COMPONENT_FACTORY ( libkigpart, KigPartFactory ) + +KAboutData* KigPart::createAboutData() +{ + return kigAboutData( "kig", I18N_NOOP( "KigPart" ) ); +} + +class SetCoordinateSystemAction + : public KSelectAction +{ + KigPart& md; +public: + SetCoordinateSystemAction( KigPart& d, KActionCollection* parent ); + void slotActivated( int index ); +}; + +SetCoordinateSystemAction::SetCoordinateSystemAction( + KigPart& d, KActionCollection* parent ) + : KSelectAction( i18n( "&Set Coordinate System" ), 0, parent, "settings_set_coordinate_system" ), + md( d ) +{ + setItems( CoordinateSystemFactory::names() ); + setCurrentItem( md.document().coordinateSystem().id() ); +} + +void SetCoordinateSystemAction::slotActivated( int index ) +{ + CoordinateSystem* sys = CoordinateSystemFactory::build( index ); + assert( sys ); + md.history()->addCommand( KigCommand::changeCoordSystemCommand( md, sys ) ); + setCurrentItem( index ); +} + +class KigPrintDialogPage + : public KPrintDialogPage +{ +public: + KigPrintDialogPage( QWidget* parent = 0, const char* name = 0 ); + ~KigPrintDialogPage(); + + void getOptions( QMap<QString,QString>& opts, bool ); + void setOptions( const QMap<QString,QString>& opts ); + bool isValid( QString& ); + +private: + QCheckBox *showgrid; + QCheckBox *showaxes; +}; + +KigPrintDialogPage::KigPrintDialogPage( QWidget* parent, const char* name ) + : KPrintDialogPage( parent, name ) +{ + setTitle( i18n( "Kig Options" ) ); + + QVBoxLayout* vl = new QVBoxLayout( this, 0 , 11 ); + + showgrid = new QCheckBox( i18n( "Show grid" ), this ); + vl->addWidget( showgrid ); + + showaxes = new QCheckBox( i18n( "Show axes" ), this ); + vl->addWidget( showaxes ); + + vl->addItem( new QSpacerItem( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding ) ); +} + +KigPrintDialogPage::~KigPrintDialogPage() +{ +} + +void KigPrintDialogPage::getOptions( QMap< QString, QString >& opts, bool ) +{ + opts[ "kde-kig-showgrid" ] = QString::number( showgrid->isChecked() ); + opts[ "kde-kig-showaxes" ] = QString::number( showaxes->isChecked() ); +} + +void KigPrintDialogPage::setOptions( const QMap< QString, QString >& opts ) +{ + QString tmp = opts[ "kde-kig-showgrid" ]; + bool bt = ( tmp != "0" ); + showgrid->setChecked( bt ); + tmp = opts[ "kde-kig-showaxes" ]; + bt = ( tmp != "0" ); + showaxes->setChecked( bt ); +} + +bool KigPrintDialogPage::isValid( QString& ) +{ + return true; +} + +KigPart::KigPart( QWidget *parentWidget, const char *, + QObject *parent, const char *name, + const QStringList& ) + : KParts::ReadWritePart( parent, name ), + mMode( 0 ), mdocument( new KigDocument() ) +{ + // we need an instance + setInstance( KigPartFactory::instance() ); + + mMode = new NormalMode( *this ); + + // we need a widget, to actually show the document + m_widget = new KigView(this, false, parentWidget, "kig_view"); + // notify the part that this is our internal widget + setWidget( m_widget ); + + // create our actions... + setupActions(); + + // set our XML-UI resource file + setXMLFile("kigpartui.rc"); + + // our types... + setupTypes(); + + // construct our command history + mhistory = new KCommandHistory(actionCollection()); + mhistory->documentSaved(); + connect( mhistory, SIGNAL( documentRestored() ), this, SLOT( setUnmodified() ) ); + + // we are read-write by default + setReadWrite(true); + + setModified (false); + + GUIActionList::instance()->regDoc( this ); +} + +void KigPart::setupActions() +{ + // save actions.. + (void) KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection()); + (void) KStdAction::save(this, SLOT(fileSave()), actionCollection()); + + // print actions + (void) KStdAction::print( this, SLOT( filePrint() ), actionCollection() ); + (void) KStdAction::printPreview( this, SLOT( filePrintPreview() ), actionCollection() ); + + // selection actions + aSelectAll = KStdAction::selectAll( + this, SLOT( slotSelectAll() ), actionCollection() ); + aDeselectAll = KStdAction::deselect( + this, SLOT( slotDeselectAll() ), actionCollection() ); + aInvertSelection = new KAction( + i18n( "Invert Selection" ), "", 0, this, + SLOT( slotInvertSelection() ), actionCollection(), + "edit_invert_selection" ); + + // we need icons... + KIconLoader* l = instance()->iconLoader(); + QPixmap tmp; + + aDeleteObjects = new KAction( + i18n("&Delete Objects"), "editdelete", Key_Delete, this, + SLOT(deleteObjects()), actionCollection(), "delete_objects"); + aDeleteObjects->setToolTip(i18n("Delete the selected objects")); + + aCancelConstruction = new KAction( + i18n("Cancel Construction"), "stop", Key_Escape, this, + SLOT(cancelConstruction()), actionCollection(), "cancel_construction"); + aCancelConstruction->setToolTip( + i18n("Cancel the construction of the object being constructed")); + aCancelConstruction->setEnabled(false); + + aShowHidden = new KAction( + i18n("U&nhide All"), 0, this, SLOT( showHidden() ), + actionCollection(), "edit_unhide_all"); + aShowHidden->setToolTip(i18n("Show all hidden objects")); + aShowHidden->setEnabled( true ); + + aNewMacro = new KAction( + i18n("&New Macro..."), "gear", 0, this, SLOT(newMacro()), + actionCollection(), "macro_action"); + aNewMacro->setToolTip(i18n("Define a new macro")); + + aConfigureTypes = new KAction( + i18n("Manage &Types..."), 0, this, SLOT(editTypes()), + actionCollection(), "types_edit"); + aConfigureTypes->setToolTip(i18n("Manage macro types.")); + + KigExportManager::instance()->addMenuAction( this, m_widget->realWidget(), + actionCollection() ); + + KAction* a = KStdAction::zoomIn( m_widget, SLOT( slotZoomIn() ), + actionCollection() ); + a->setToolTip( i18n( "Zoom in on the document" ) ); + a->setWhatsThis( i18n( "Zoom in on the document" ) ); + + a = KStdAction::zoomOut( m_widget, SLOT( slotZoomOut() ), + actionCollection() ); + a->setToolTip( i18n( "Zoom out of the document" ) ); + a->setWhatsThis( i18n( "Zoom out of the document" ) ); + + a = KStdAction::fitToPage( m_widget, SLOT( slotRecenterScreen() ), + actionCollection() ); + // grr.. why isn't there an icon for this.. + a->setIconSet( QIconSet( l->loadIcon( "view_fit_to_page", KIcon::Toolbar ) ) ); + a->setToolTip( i18n( "Recenter the screen on the document" ) ); + a->setWhatsThis( i18n( "Recenter the screen on the document" ) ); + +#ifdef KDE_IS_VERSION +#if KDE_IS_VERSION(3,1,90) +#define KIG_PART_CPP_STD_FULLSCREEN_ACTION +#endif +#endif +#ifdef KIG_PART_CPP_STD_FULLSCREEN_ACTION + a = KStdAction::fullScreen( m_widget, SLOT( toggleFullScreen() ), actionCollection(), (QWidget*)(widget()->parent()),"fullscreen" ); +#else + tmp = l->loadIcon( "window_fullscreen", KIcon::Toolbar ); + a = new KAction( + i18n( "Full Screen" ), tmp, CTRL+SHIFT+Key_F, + m_widget, SLOT( toggleFullScreen() ), + actionCollection(), "fullscreen" ); +#endif + a->setToolTip( i18n( "View this document full-screen." ) ); + a->setWhatsThis( i18n( "View this document full-screen." ) ); + + // TODO: an icon for this.. + a = new KAction( + i18n( "&Select Shown Area" ), "viewmagfit", 0, m_widget, SLOT( zoomRect() ), + actionCollection(), "view_select_shown_rect" ); + a->setToolTip( i18n( "Select the area that you want to be shown in the window." ) ); + a->setWhatsThis( i18n( "Select the area that you want to be shown in the window." ) ); + + a = new KAction( + i18n( "S&elect Zoom Area" ), "viewmag", 0, m_widget, SLOT( zoomArea() ), + actionCollection(), "view_zoom_area" ); +// a->setToolTip( i18n( "Select the area that you want to be shown in the window." ) ); +// a->setWhatsThis( i18n( "Select the area that you want to be shown in the window." ) ); + + aToggleGrid = new KToggleAction( + i18n( "Show &Grid" ), 0, this, SLOT( toggleGrid() ), + actionCollection(), "settings_show_grid" ); + aToggleGrid->setToolTip( i18n( "Show or hide the grid." ) ); + aToggleGrid->setChecked( true ); + + aToggleAxes = new KToggleAction( + i18n( "Show &Axes" ), 0, this, SLOT( toggleAxes() ), + actionCollection(), "settings_show_axes" ); + aToggleAxes->setToolTip( i18n( "Show or hide the axes." ) ); + aToggleAxes->setChecked( true ); + + aToggleNightVision = new KToggleAction( + i18n( "Wear Infrared Glasses" ), 0, this, SLOT( toggleNightVision() ), + actionCollection(), "settings_toggle_nightvision" ); + aToggleNightVision->setToolTip( i18n( "Enable/Disable hidden objects visibility." ) ); + aToggleNightVision->setChecked( false ); + + // select coordinate system KActionMenu.. + aCoordSystem = new SetCoordinateSystemAction( *this, actionCollection() ); +} + +void KigPart::setupTypes() +{ + setupBuiltinStuff(); + setupBuiltinMacros(); + setupMacroTypes(); + GUIActionList& l = *GUIActionList::instance(); + typedef GUIActionList::avectype::const_iterator iter; + for ( iter i = l.actions().begin(); i != l.actions().end(); ++i ) + { + KigGUIAction* ret = new KigGUIAction( *i, *this, actionCollection() ); + aActions.push_back( ret ); + ret->plug( this ); + }; +} + +KigPart::~KigPart() +{ + GUIActionList::instance()->unregDoc( this ); + + // save our types... + saveTypes(); + + // objects get deleted automatically, when mobjsref gets + // destructed.. + + delete_all( aActions.begin(), aActions.end() ); + aActions.clear(); + + // cleanup + delete mMode; + delete mhistory; + + delete mdocument; +} + +bool KigPart::openFile() +{ + QFileInfo fileinfo( m_file ); + if ( ! fileinfo.exists() ) + { + KMessageBox::sorry( widget(), + i18n( "The file \"%1\" you tried to open does not exist. " + "Please verify that you entered the correct path." ).arg( m_file ), + i18n( "File Not Found" ) ); + return false; + }; + + // m_file is always local, so we can use findByPath instead of + // findByURL... + KMimeType::Ptr mimeType = KMimeType::findByPath ( m_file ); + kdDebug() << k_funcinfo << "mimetype: " << mimeType->name() << endl; + KigFilter* filter = KigFilters::instance()->find( mimeType->name() ); + if ( !filter ) + { + // we don't support this mime type... + KMessageBox::sorry + ( + widget(), + i18n( "You tried to open a document of type \"%1\"; unfortunately, " + "Kig does not support this format. If you think the format in " + "question would be worth implementing support for, you can " + "always ask us nicely on mailto:toscano.pino@tiscali.it " + "or do the work yourself and send me a patch." + ).arg(mimeType->name()), + i18n( "Format Not Supported" ) + ); + return false; + }; + + KigDocument* newdoc = filter->load (m_file); + if ( !newdoc ) + { + closeURL(); + m_url = KURL(); + return false; + } + delete mdocument; + mdocument = newdoc; + coordSystemChanged( mdocument->coordinateSystem().id() ); + aToggleGrid->setChecked( mdocument->grid() ); + aToggleAxes->setChecked( mdocument->axes() ); + aToggleNightVision->setChecked( mdocument->getNightVision() ); + + setModified(false); + mhistory->clear(); + + std::vector<ObjectCalcer*> tmp = calcPath( getAllParents( getAllCalcers( document().objects() ) ) ); + for ( std::vector<ObjectCalcer*>::iterator i = tmp.begin(); i != tmp.end(); ++i ) + ( *i )->calc( document() ); + emit recenterScreen(); + + redrawScreen(); + + return true; +} + +bool KigPart::saveFile() +{ + if ( m_file.isEmpty() || m_bTemp ) return internalSaveAs(); + // mimetype: + KMimeType::Ptr mimeType = KMimeType::findByPath ( m_file ); + if ( mimeType->name() != "application/x-kig" ) + { + // we don't support this mime type... + if( KMessageBox::warningYesNo( widget(), + i18n( "Kig does not support saving to any other file format than " + "its own. Save to Kig's format instead?" ), + i18n( "Format Not Supported" ), i18n("Save Kig Format"), KStdGuiItem::cancel() ) == KMessageBox::No ) + return false; + internalSaveAs(); + }; + + if ( KigFilters::instance()->save( document(), m_file ) ) + { + setModified ( false ); + mhistory->documentSaved(); + return true; + } + return false; +} + +void KigPart::addObject(ObjectHolder* o) +{ + mhistory->addCommand( KigCommand::addCommand( *this, o ) ); +} + +void KigPart::addObjects( const std::vector<ObjectHolder*>& os ) +{ + mhistory->addCommand( KigCommand::addCommand( *this, os ) ); +} + +void KigPart::_addObject( ObjectHolder* o ) +{ + document().addObject( o ); + setModified(true); +} + +void KigPart::delObject( ObjectHolder* o ) +{ + // we delete all children and their children etc. too... + std::vector<ObjectHolder*> os; + os.push_back( o ); + delObjects( os ); +} + +void KigPart::_delObjects( const std::vector<ObjectHolder*>& o ) +{ + document().delObjects( o ); + setModified( true ); +} + +void KigPart::_delObject(ObjectHolder* o) +{ + document().delObject( o ); + setModified(true); +} + +void KigPart::setMode( KigMode* m ) +{ + mMode = m; + m->enableActions(); + redrawScreen(); +} + +void KigPart::_addObjects( const std::vector<ObjectHolder*>& os ) +{ + document().addObjects( os ); + setModified( true ); +} + +void KigPart::deleteObjects() +{ + mode()->deleteObjects(); +} + +void KigPart::cancelConstruction() +{ + mode()->cancelConstruction(); +} + +void KigPart::showHidden() +{ + mode()->showHidden(); +} + +void KigPart::newMacro() +{ + mode()->newMacro(); +} + +void KigPart::editTypes() +{ + mode()->editTypes(); +} + +void KigPart::setUnmodified() +{ + setModified( false ); +} + +KCommandHistory* KigPart::history() +{ + return mhistory; +} + +void KigPart::delObjects( const std::vector<ObjectHolder*>& os ) +{ + if ( os.size() < 1 ) return; + std::set<ObjectHolder*> delobjs; + + std::set<ObjectCalcer*> delcalcers = getAllChildren( getAllCalcers( os ) ); + std::map<ObjectCalcer*, ObjectHolder*> holdermap; + + std::set<ObjectHolder*> curobjs = document().objectsSet(); + + for ( std::set<ObjectHolder*>::iterator i = curobjs.begin(); + i != curobjs.end(); ++i ) + holdermap[( *i )->calcer()] = *i; + + for ( std::set<ObjectCalcer*>::iterator i = delcalcers.begin(); + i != delcalcers.end(); ++i ) + { + std::map<ObjectCalcer*, ObjectHolder*>::iterator j = holdermap.find( *i ); + if ( j != holdermap.end() ) + delobjs.insert( j->second ); + } + + assert( delobjs.size() >= os.size() ); + + std::vector<ObjectHolder*> delobjsvect( delobjs.begin(), delobjs.end() ); + mhistory->addCommand( KigCommand::removeCommand( *this, delobjsvect ) ); +} + +void KigPart::enableConstructActions( bool enabled ) +{ + for_each( aActions.begin(), aActions.end(), + bind2nd( mem_fun( &KAction::setEnabled ), + enabled ) ); +} + +void KigPart::unplugActionLists() +{ + unplugActionList( "user_conic_types" ); + unplugActionList( "user_segment_types" ); + unplugActionList( "user_point_types" ); + unplugActionList( "user_circle_types" ); + unplugActionList( "user_line_types" ); + unplugActionList( "user_other_types" ); + unplugActionList( "user_types" ); +} + +void KigPart::plugActionLists() +{ + plugActionList( "user_conic_types", aMNewConic ); + plugActionList( "user_segment_types", aMNewSegment ); + plugActionList( "user_point_types", aMNewPoint ); + plugActionList( "user_circle_types", aMNewCircle ); + plugActionList( "user_line_types", aMNewLine ); + plugActionList( "user_other_types", aMNewOther ); + plugActionList( "user_types", aMNewAll ); +} + +void KigPart::emitStatusBarText( const QString& text ) +{ + emit setStatusBarText( text ); +} + +void KigPart::fileSaveAs() +{ + internalSaveAs(); +} + +void KigPart::fileSave() +{ + save(); +} + +bool KigPart::internalSaveAs() +{ + // this slot is connected to the KStdAction::saveAs action... + QString formats = i18n( "*.kig|Kig Documents (*.kig)\n" + "*.kigz|Compressed Kig Documents (*.kigz)" ); + + // formats += "\n"; + // formats += KImageIO::pattern( KImageIO::Writing ); + + QString file_name = KFileDialog::getSaveFileName(":document", formats ); + if (file_name.isEmpty()) return false; + else if ( QFileInfo( file_name ).exists() ) + { + int ret = KMessageBox::warningContinueCancel( m_widget, + i18n( "The file \"%1\" already exists. Do you wish to overwrite it?" ) + .arg( file_name ), i18n( "Overwrite File?" ), i18n("Overwrite") ); + if ( ret != KMessageBox::Continue ) + { + return false; + } + } + saveAs(KURL::fromPathOrURL( file_name )); + return true; +} + +void KigPart::runMode( KigMode* m ) +{ + KigMode* prev = mMode; + + setMode( m ); + +#if QT_VERSION >= 0x030100 + (void) kapp->eventLoop()->enterLoop(); +#else + (void) kapp->enter_loop(); +#endif + + setMode( prev ); + redrawScreen(); +} + +void KigPart::doneMode( KigMode* d ) +{ + assert( d == mMode ); + // pretend to use this var.. + (void)d; +#if QT_VERSION >= 0x030100 + kapp->eventLoop()->exitLoop(); +#else + kapp->exit_loop(); +#endif +} + +void KigPart::actionRemoved( GUIAction* a, GUIUpdateToken& t ) +{ + KigGUIAction* rem = 0; + for ( std::vector<KigGUIAction*>::iterator i = aActions.begin(); i != aActions.end(); ++i ) + { + if ( (*i)->guiAction() == a ) + { + rem = *i; + aActions.erase( i ); + break; + } + }; + assert( rem ); + aMNewSegment.remove( rem ); + aMNewConic.remove( rem ); + aMNewPoint.remove( rem ); + aMNewCircle.remove( rem ); + aMNewLine.remove( rem ); + aMNewOther.remove( rem ); + aMNewAll.remove( rem ); + t.push_back( rem ); +} + +void KigPart::actionAdded( GUIAction* a, GUIUpdateToken& ) +{ + KigGUIAction* ret = new KigGUIAction( a, *this, actionCollection() ); + aActions.push_back( ret ); + ret->plug( this ); +} + +void KigPart::endGUIActionUpdate( GUIUpdateToken& t ) +{ + unplugActionLists(); + plugActionLists(); + delete_all( t.begin(), t.end() ); + t.clear(); +} + +KigPart::GUIUpdateToken KigPart::startGUIActionUpdate() +{ + return GUIUpdateToken(); +} + +void KigPart::setupMacroTypes() +{ + static bool alreadysetup = false; + if ( ! alreadysetup ) + { + alreadysetup = true; + + // the user's saved macro types: + QStringList dataFiles = + KGlobal::dirs()->findAllResources("appdata", "kig-types/*.kigt", + true, false ); + std::vector<Macro*> macros; + for ( QStringList::iterator file = dataFiles.begin(); + file != dataFiles.end(); ++file ) + { + std::vector<Macro*> nmacros; + bool ok = MacroList::instance()->load( *file, nmacros, *this ); + if ( ! ok ) continue; + copy( nmacros.begin(), nmacros.end(), back_inserter( macros ) ); + } + MacroList::instance()->add( macros ); + }; + // hack: we need to plug the action lists _after_ the gui is + // built.. i can't find a better solution than this... + QTimer::singleShot( 0, this, SLOT( plugActionLists() ) ); +} + +void KigPart::setupBuiltinMacros() +{ + static bool alreadysetup = false; + if ( ! alreadysetup ) + { + alreadysetup = true; + // builtin macro types ( we try to make the user think these are + // normal types ).. + QStringList builtinfiles = + KGlobal::dirs()->findAllResources( "appdata", "builtin-macros/*.kigt", true, false ); + for ( QStringList::iterator file = builtinfiles.begin(); + file != builtinfiles.end(); ++file ) + { + std::vector<Macro*> macros; + bool ok = MacroList::instance()->load( *file, macros, *this ); + if ( ! ok ) continue; + for ( uint i = 0; i < macros.size(); ++i ) + { + ObjectConstructorList* ctors = ObjectConstructorList::instance(); + GUIActionList* actions = GUIActionList::instance(); + Macro* macro = macros[i]; + macro->ctor->setBuiltin( true ); + ctors->add( macro->ctor ); + actions->add( macro->action ); + macro->ctor = 0; + macro->action = 0; + delete macro; + }; + }; + }; +} + +void KigPart::addWidget( KigWidget* v ) +{ + mwidgets.push_back( v ); +} + +void KigPart::delWidget( KigWidget* v ) +{ + mwidgets.erase( std::remove( mwidgets.begin(), mwidgets.end(), v ), mwidgets.end() ); +} + +void KigPart::filePrintPreview() +{ + KPrinter printer; + printer.setPreviewOnly( true ); + doPrint( printer ); +} + +void KigPart::filePrint() +{ + KPrinter printer; + KigPrintDialogPage* kp = new KigPrintDialogPage(); + printer.addDialogPage( kp ); + printer.setFullPage( true ); + printer.setOption( "kde-kig-showgrid", QString::number( document().grid() ) ); + printer.setOption( "kde-kig-showaxes", QString::number( document().axes() ) ); + printer.setPageSelection( KPrinter::ApplicationSide ); + if ( printer.setup( m_widget, i18n("Print Geometry") ) ) + { + doPrint( printer ); + }; +} + +void KigPart::doPrint( KPrinter& printer ) +{ + QPaintDeviceMetrics metrics( &printer ); + Rect rect = document().suggestedRect(); + QRect qrect( 0, 0, metrics.width(), metrics.height() ); + if ( rect.width() * qrect.height() > rect.height() * qrect.width() ) + { + // qrect is too high.. + int nh = static_cast<int>( qrect.width() * rect.height() / rect.width() ); + int rest = qrect.height() - nh; + qrect.setTop( qrect.top() - rest / 2 ); + qrect.setTop( rest / 2 ); + } + else + { + // qrect is too wide.. + int nw = static_cast<int>( qrect.height() * rect.width() / rect.height() ); + int rest = qrect.width() - nw; + qrect.setLeft( rest / 2 ); + qrect.setRight( qrect.right() - rest / 2 ); + }; + ScreenInfo si( rect, qrect ); + KigPainter painter( si, &printer, document() ); + painter.setWholeWinOverlay(); + bool sg = true; + bool sa = true; + if ( !printer.previewOnly() ) + { + sg = ( printer.option( "kde-kig-showgrid" ) != "0" ); + sa = ( printer.option( "kde-kig-showaxes" ) != "0" ); + } + else + { + sg = document().grid(); + sg = document().axes(); + } + painter.drawGrid( document().coordinateSystem(), sg, sa ); + painter.drawObjects( document().objects(), false ); +} + +void KigPart::slotSelectAll() +{ + mMode->selectAll(); +} + +void KigPart::slotDeselectAll() +{ + mMode->deselectAll(); +} + +void KigPart::slotInvertSelection() +{ + mMode->invertSelection(); +} + +void KigPart::hideObjects( const std::vector<ObjectHolder*>& inos ) +{ + std::vector<ObjectHolder*> os; + for (std::vector<ObjectHolder*>::const_iterator i = inos.begin(); i != inos.end(); ++i ) + { + if ( (*i)->shown() ) + os.push_back( *i ); + }; + KigCommand* kc = 0; + if ( os.size() == 0 ) return; + else if ( os.size() == 1 ) + kc = new KigCommand( *this, os[0]->imp()->type()->hideAStatement() ); + else kc = new KigCommand( *this, i18n( "Hide %n Object", "Hide %n Objects", os.size() ) ); + for ( std::vector<ObjectHolder*>::iterator i = os.begin(); + i != os.end(); ++i ) + kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyShown( false ) ) ); + mhistory->addCommand( kc ); +} + +void KigPart::showObjects( const std::vector<ObjectHolder*>& inos ) +{ + std::vector<ObjectHolder*> os; + for (std::vector<ObjectHolder*>::const_iterator i = inos.begin(); i != inos.end(); ++i ) + { + if ( !(*i)->shown() ) + os.push_back( *i ); + }; + KigCommand* kc = 0; + if ( os.size() == 0 ) return; + else if ( os.size() == 1 ) + kc = new KigCommand( *this, os[0]->imp()->type()->showAStatement() ); + else kc = new KigCommand( *this, i18n( "Show %n Object", "Show %n Objects", os.size() ) ); + for ( std::vector<ObjectHolder*>::iterator i = os.begin(); + i != os.end(); ++i ) + kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyShown( true ) ) ); + mhistory->addCommand( kc ); +} + +void KigPart::redrawScreen( KigWidget* w ) +{ + mode()->redrawScreen( w ); +} + +void KigPart::redrawScreen() +{ + for ( std::vector<KigWidget*>::iterator i = mwidgets.begin(); + i != mwidgets.end(); ++i ) + { + mode()->redrawScreen( *i ); + } +} + +const KigDocument& KigPart::document() const +{ + return *mdocument; +} + +KigDocument& KigPart::document() +{ + return *mdocument; +} + +extern "C" int convertToNative( const KURL& url, const QCString& outfile ) +{ + kdDebug() << "converting " << url.prettyURL() << " to " << outfile << endl; + + if ( ! url.isLocalFile() ) + { + // TODO + kdError() << "--convert-to-native only supports local files for now." << endl; + return -1; + } + + QString file = url.path(); + + QFileInfo fileinfo( file ); + if ( ! fileinfo.exists() ) + { + kdError() << "The file \"" << file << "\" does not exist" << endl; + return -1; + }; + + KMimeType::Ptr mimeType = KMimeType::findByPath ( file ); + kdDebug() << k_funcinfo << "mimetype: " << mimeType->name() << endl; + KigFilter* filter = KigFilters::instance()->find( mimeType->name() ); + if ( !filter ) + { + kdError() << "The file \"" << file << "\" is of a filetype not currently supported by Kig." << endl; + return -1; + }; + + KigDocument* doc = filter->load (file); + if ( !doc ) + { + kdError() << "Parse error in file \"" << file << "\"." << endl; + return -1; + } + + std::vector<ObjectCalcer*> tmp = calcPath( getAllParents( getAllCalcers( doc->objects() ) ) ); + for ( std::vector<ObjectCalcer*>::iterator i = tmp.begin(); i != tmp.end(); ++i ) + ( *i )->calc( *doc ); + for ( std::vector<ObjectCalcer*>::iterator i = tmp.begin(); i != tmp.end(); ++i ) + ( *i )->calc( *doc ); + + QString out = ( outfile == "-" ) ? QString::null : outfile; + bool success = KigFilters::instance()->save( *doc, out ); + if ( !success ) + { + kdError() << "something went wrong while saving" << endl; + return -1; + } + + delete doc; + + return 0; +} + +void KigPart::toggleGrid() +{ + bool toshow = !mdocument->grid(); + aToggleGrid->setChecked( toshow ); + mdocument->setGrid( toshow ); + + redrawScreen(); +} + +void KigPart::toggleAxes() +{ + bool toshow = !mdocument->axes(); + aToggleAxes->setChecked( toshow ); + mdocument->setAxes( toshow ); + + redrawScreen(); +} + +void KigPart::toggleNightVision() +{ + bool nv = !mdocument->getNightVision(); + aToggleNightVision->setChecked( nv ); + mdocument->setNightVision( nv ); + + redrawScreen(); +} + +void KigPart::coordSystemChanged( int id ) +{ + aCoordSystem->setCurrentItem( id ); +} + +void KigPart::saveTypes() +{ + QString typesDir = KGlobal::dirs()->saveLocation( "appdata", "kig-types" ); + if ( typesDir[ typesDir.length() - 1 ] != '/' ) + typesDir += '/'; + QString typesFileWithPath = typesDir + typesFile; + + // removing existant types file + if ( QFile::exists( typesFileWithPath ) ) + QFile::remove( typesFileWithPath ); + + MacroList* macrolist = MacroList::instance(); + macrolist->save( macrolist->macros(), typesFileWithPath ); +} + +void KigPart::loadTypes() +{ + QString typesDir = KGlobal::dirs()->saveLocation( "appdata", "kig-types" ); + if ( typesDir[ typesDir.length() - 1 ] != '/' ) + typesDir += '/'; + QString typesFileWithPath = typesDir + typesFile; + + if ( QFile::exists( typesFileWithPath ) ) + { + std::vector<Macro*> macros; + MacroList::instance()->load( typesFileWithPath, macros, *this ); + MacroList::instance()->add( macros ); + } +} + +void KigPart::deleteTypes() +{ + unplugActionLists(); + typedef MacroList::vectype vec; + MacroList* macrolist = MacroList::instance(); + const vec& macros = macrolist->macros(); + for ( vec::const_reverse_iterator i = macros.rbegin(); i != macros.rend(); ++i ) + { + macrolist->remove( *i ); + } + plugActionLists(); +} diff --git a/kig/kig/kig_part.desktop b/kig/kig/kig_part.desktop new file mode 100644 index 00000000..cffd6e3d --- /dev/null +++ b/kig/kig/kig_part.desktop @@ -0,0 +1,16 @@ +[Desktop Entry] +Name=KigPart +Name[ar]=جزء كيج +Name[bn]=কিগপার্ট +Name[et]=Kigi komponent +Name[hi]=के-इग-पार्ट +Name[ne]=किग पार्ट +Name[sv]=Kigdel +Name[ta]=கிக்பகுதி +Name[ven]=TshipidatshaKig +Name[zh_CN]=Kig 组件 +MimeType=application/x-kig;application/x-kgeo; +ServiceTypes=KParts/ReadOnlyPart,KParts/ReadWritePart +X-KDE-Library=libkigpart +Type=Service +Icon=kig diff --git a/kig/kig/kig_part.h b/kig/kig/kig_part.h new file mode 100644 index 00000000..2084d0a9 --- /dev/null +++ b/kig/kig/kig_part.h @@ -0,0 +1,257 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + + +#ifndef KIGPART_H +#define KIGPART_H + +#include <qptrlist.h> + +#include <kparts/part.h> + +#include "../objects/common.h" + +class KAboutData; +class KActionMenu; +class KCommandHistory; +class KPrinter; +class KSelectAction; +class KToolBar; +class KToggleAction; +class KURL; +class QWidget; + +class Coordinate; +class CoordinateSystem; +class GUIAction; +class KigGUIAction; +class KigMode; +class KigObjectsPopup; +class KigView; +class MacroWizardImpl; +class ObjectHolder; +class Rect; +class ScreenInfo; + +/** + * This is a "Part". It that does all the real work in a KPart + * application. + * Briefly, it holds the data of the document, and acts as an + * interface to shells + * + * @short Main Part + */ +class KigPart : public KParts::ReadWritePart +{ + Q_OBJECT +public: + /** + * Default constructor + */ + KigPart( QWidget* parentWidget, const char* widgetName, + QObject* parent = 0, const char* name = 0, + const QStringList& = QStringList() + ); + + /** + * Destructor + */ + virtual ~KigPart(); + +/*********************** KPart interface *************************/ + +protected: + /** + * load our internal document from m_file + */ + virtual bool openFile(); + + /** + * save our internal document to m_file + */ + virtual bool saveFile(); + +public: + void emitStatusBarText( const QString& text ); + void redrawScreen(); + void redrawScreen( KigWidget* w ); + +public slots: + void fileSaveAs(); + void fileSave(); + + void filePrint(); + void filePrintPreview(); + + void slotSelectAll(); + void slotDeselectAll(); + void slotInvertSelection(); + + void unplugActionLists(); + void plugActionLists(); + + void deleteObjects(); + void cancelConstruction(); + void showHidden(); + void newMacro(); + void editTypes(); + + void toggleGrid(); + void toggleAxes(); + void toggleNightVision(); + + /** + * equivalent to setModified( false ); ( did i mention i don't like + * signals/slots for being this inflexible... + * this is connected to mhistory->documentRestored(); + */ + void setUnmodified(); + + /****************** cooperation with stuff ******************/ +public: + void addWidget( KigWidget* ); + void delWidget( KigWidget* ); + + KigMode* mode() const { return mMode; } + void setMode( KigMode* ); + void runMode( KigMode* ); + void doneMode( KigMode* ); + + void coordSystemChanged( int ); + +signals: // these signals are for telling KigView it should do something... + /** + * emitted when we want to suggest a new size for the view + * ( basically after loading a file, and on startup... ) + */ + void recenterScreen(); + +/************** working with our internal document **********/ +public: + // guess what these do... + // actually, they only add a command object to the history, the real + // work is done in _addObject() and _delObject() + void addObject(ObjectHolder* inObject); + void addObjects( const std::vector<ObjectHolder*>& os ); + void delObject(ObjectHolder* inObject); + void delObjects( const std::vector<ObjectHolder*>& os ); + void hideObjects( const std::vector<ObjectHolder*>& os ); + void showObjects( const std::vector<ObjectHolder*>& os ); + + void _addObject( ObjectHolder* inObject ); + void _addObjects( const std::vector<ObjectHolder*>& o); + void _delObject( ObjectHolder* inObject ); + void _delObjects( const std::vector<ObjectHolder*>& o ); + +/************* internal stuff *************/ +protected: + bool internalSaveAs(); + +public: + static KAboutData* createAboutData(); +protected: + void setupActions(); + void setupTypes(); + void setupBuiltinMacros(); + void setupMacroTypes(); + +protected: + KigMode* mMode; + KSelectAction* aCoordSystem; + + /** + * the command history + */ + KCommandHistory* mhistory; + +public: + // actions: this is an annoying case, didn't really fit into my + // model with KigModes.. This is how it works now: + // the actions are owned by the Part, because we need them on + // constructing the GUI ( actions appearing when you switch modes + // would not be nice, imho ). On setting the KigPart mode, we + // connect the actions to the current mode, and disconnect them from + // the previous mode. Enabling/disabling is done at the same time, + // of course.. + // some MenuActions.. + QPtrList<KAction> aMNewSegment; + QPtrList<KAction> aMNewPoint; + QPtrList<KAction> aMNewCircle; + QPtrList<KAction> aMNewLine; + QPtrList<KAction> aMNewOther; + QPtrList<KAction> aMNewAll; + QPtrList<KAction> aMNewConic; + + + KAction* aCancelConstruction; + KAction* aSelectAll; + KAction* aDeselectAll; + KAction* aInvertSelection; + KAction* aDeleteObjects; + KAction* aNewMacro; + KAction* aShowHidden; + KAction* aConfigureTypes; + KToggleAction* aToggleGrid; + KToggleAction* aToggleAxes; + KToggleAction* aToggleNightVision; + std::vector<KigGUIAction*> aActions; + + /** + * the "token" keeps some objects that should be deleted, we only + * delete them after we replug the actionLists.. calling these + * functions should be done like: + * \code + * GUIUpdateToken t = doc->startGUIActionUpdate(); + * doc->action[Added|Removed]( act, t ); + * ... + * doc->endGUIActionUpdate( t ); + * \endcode + */ + typedef std::vector<KigGUIAction*> GUIUpdateToken; + GUIUpdateToken startGUIActionUpdate(); + void actionAdded( GUIAction* a, GUIUpdateToken& t ); + void actionRemoved( GUIAction* a, GUIUpdateToken& t ); + void endGUIActionUpdate( GUIUpdateToken& t ); + + KCommandHistory* history(); + + void enableConstructActions( bool enabled ); + +protected: + void doPrint( KPrinter& printer ); + + std::vector<KigWidget*> mwidgets; + + KigView* m_widget; + + KigDocument* mdocument; +public: + const KigDocument& document() const; + KigDocument& document(); + +/***************** types handling *******************/ + void saveTypes(); + void loadTypes(); + void deleteTypes(); + +}; + +#endif // KIGPART_H + diff --git a/kig/kig/kig_view.cpp b/kig/kig/kig_view.cpp new file mode 100644 index 00000000..7d36bc14 --- /dev/null +++ b/kig/kig/kig_view.cpp @@ -0,0 +1,593 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + +#include "kig_view.h" +#include "kig_view.moc" + +#include "kig_part.h" +#include "kig_document.h" +#include "kig_commands.h" +#include "../misc/coordinate_system.h" +#include "../misc/kiginputdialog.h" +#include "../misc/kigpainter.h" +#include "../modes/mode.h" +#include "../modes/dragrectmode.h" + +#include <qdialog.h> +#include <qevent.h> +#include <qwhatsthis.h> +#include <qlayout.h> +#include <qscrollbar.h> + +#include <kdebug.h> +#include <kcursor.h> +#include <klocale.h> +#include <kapplication.h> +#include <kstdaction.h> +#include <kaction.h> +#include <kiconloader.h> + +#include <cmath> +#include <algorithm> + +kdbgstream& operator<< ( kdbgstream& s, const QPoint& t ) +{ + s << "x: " << t.x() << " y: " << t.y(); + return s; +} + +KigWidget::KigWidget( KigPart* part, + KigView* view, + QWidget* parent, + const char* name, + bool fullscreen ) + : QWidget( parent, name, + fullscreen ? WStyle_Customize | WStyle_NoBorder : 0 ), + mpart( part ), + mview( view ), + stillPix(size()), + curPix(size()), + msi( Rect(), rect() ), + misfullscreen( fullscreen ) +{ + part->addWidget(this); + + setFocusPolicy(ClickFocus); + setBackgroundMode( Qt::NoBackground ); + setMouseTracking(true); + + curPix.resize( size() ); + stillPix.resize( size() ); +} + +KigWidget::~KigWidget() +{ + mpart->delWidget( this ); +} + +void KigWidget::paintEvent(QPaintEvent*) +{ + updateEntireWidget(); +} + +void KigWidget::mousePressEvent (QMouseEvent* e) +{ + if( e->button() & Qt::LeftButton ) + return mpart->mode()->leftClicked( e, this ); + if ( e->button() & Qt::MidButton ) + return mpart->mode()->midClicked( e, this ); + if ( e->button() & Qt::RightButton ) + return mpart->mode()->rightClicked( e, this ); +} + +void KigWidget::mouseMoveEvent (QMouseEvent* e) +{ + if( e->state() & Qt::LeftButton ) + return mpart->mode()->leftMouseMoved( e, this ); + if ( e->state() & Qt::MidButton ) + return mpart->mode()->midMouseMoved( e, this ); + if ( e->state() & Qt::RightButton ) + return mpart->mode()->rightMouseMoved( e, this ); + return mpart->mode()->mouseMoved( e, this ); +} + +void KigWidget::mouseReleaseEvent (QMouseEvent* e) +{ + if( e->state() & Qt::LeftButton ) + return mpart->mode()->leftReleased( e, this ); + if ( e->state() & Qt::MidButton ) + return mpart->mode()->midReleased( e, this ); + if ( e->state() & Qt::RightButton ) + return mpart->mode()->rightReleased( e, this ); +} + +void KigWidget::updateWidget( const std::vector<QRect>& overlay ) +{ +#undef SHOW_OVERLAY_RECTS +#ifdef SHOW_OVERLAY_RECTS + QPainter debug (this, this); + debug.setPen(Qt::yellow); +#endif // SHOW_OVERLAY_RECTS + // we undo our old changes... + for ( std::vector<QRect>::const_iterator i = oldOverlay.begin(); i != oldOverlay.end(); ++i ) + bitBlt( this, i->topLeft(), &curPix, *i ); + // we add our new changes... + for ( std::vector<QRect>::const_iterator i = overlay.begin(); i != overlay.end(); ++i ) + { + bitBlt( this, i->topLeft(), &curPix, *i ); +#ifdef SHOW_OVERLAY_RECTS + debug.drawRect(*i); +#endif + }; + oldOverlay = overlay; +} + +void KigWidget::updateEntireWidget() +{ + std::vector<QRect> overlay; + overlay.push_back( QRect( QPoint( 0, 0 ), size() ) ); + updateWidget( overlay ); +} + +void KigWidget::resizeEvent( QResizeEvent* e ) +{ + QSize osize = e->oldSize(); + QSize nsize = e->size(); + Rect orect = msi.shownRect(); + + curPix.resize( nsize ); + stillPix.resize( nsize ); + msi.setViewRect( rect() ); + + Rect nrect( 0., 0., + orect.width() * nsize.width() / osize.width(), + orect.height() * nsize.height() / osize.height() ); + nrect = matchScreenShape( nrect ); + nrect.setCenter( orect.center() ); + msi.setShownRect( nrect ); + + // horrible hack... We need to somehow differentiate between the + // resizeEvents we get on startup, and the ones generated by the + // user. The first require recentering the screen, the latter + // don't.. + if ( nsize.width() / osize.width() > 4 ) recenterScreen(); + + mpart->redrawScreen( this ); + updateScrollBars(); +} + +void KigWidget::updateCurPix( const std::vector<QRect>& ol ) +{ + // we make curPix look like stillPix again... + for ( std::vector<QRect>::const_iterator i = oldOverlay.begin(); i != oldOverlay.end(); ++i ) + bitBlt( &curPix, i->topLeft(), &stillPix, *i ); + for ( std::vector<QRect>::const_iterator i = ol.begin(); i != ol.end(); ++i ) + bitBlt( &curPix, i->topLeft(), &stillPix, *i ); + + // we add ol to oldOverlay, so that part of the widget will be + // updated too in updateWidget... + std::copy( ol.begin(), ol.end(), std::back_inserter( oldOverlay ) ); +} + +void KigWidget::recenterScreen() +{ + msi.setShownRect( matchScreenShape( mpart->document().suggestedRect() ) ); +} + +Rect KigWidget::matchScreenShape( const Rect& r ) const +{ + return r.matchShape( Rect::fromQRect( rect() ) ); +} + +void KigWidget::slotZoomIn() +{ + Rect nr = msi.shownRect(); + Coordinate c = nr.center(); + nr /= 2; + nr.setCenter( c ); + KigCommand* cd = + new KigCommand( *mpart, + i18n( "Zoom In" ) ); + cd->addTask( new KigViewShownRectChangeTask( *this, nr ) ); + mpart->history()->addCommand( cd ); +} + +void KigWidget::slotZoomOut() +{ + Rect nr = msi.shownRect(); + Coordinate c = nr.center(); + nr *= 2; + nr.setCenter( c ); + + // zooming in is undoable.. I know this isn't really correct, + // because the current view doesn't really belong to the document ( + // althought KGeo and KSeg both save them along, iirc ). However, + // undoing a zoom or another operation affecting the window seems a + // bit too useful to not be available. Please try to convince me if + // you feel otherwise ;-) + KigCommand* cd = + new KigCommand( *mpart, + i18n( "Zoom Out" ) ); + cd->addTask( new KigViewShownRectChangeTask( *this, nr ) ); + mpart->history()->addCommand( cd ); +} + +void KigWidget::clearStillPix() +{ + stillPix.fill(Qt::white); + oldOverlay.clear(); + oldOverlay.push_back ( QRect( QPoint(0,0), size() ) ); +} + +void KigWidget::redrawScreen( const std::vector<ObjectHolder*>& selection, bool dos ) +{ + std::vector<ObjectHolder*> nonselection; + std::set<ObjectHolder*> objs = mpart->document().objectsSet(); + std::set_difference( objs.begin(), objs.end(), selection.begin(), selection.end(), + std::back_inserter( nonselection ) ); + + // update the screen... + clearStillPix(); + KigPainter p( msi, &stillPix, mpart->document() ); + p.drawGrid( mpart->document().coordinateSystem(), mpart->document().grid(), + mpart->document().axes() ); + p.drawObjects( selection, true ); + p.drawObjects( nonselection, false ); + updateCurPix( p.overlay() ); + if ( dos ) updateEntireWidget(); +} + +const ScreenInfo& KigWidget::screenInfo() const +{ + return msi; +} + +const Rect KigWidget::showingRect() const +{ + return msi.shownRect(); +} + +const Coordinate KigWidget::fromScreen( const QPoint& p ) +{ + return msi.fromScreen( p ); +} + +double KigWidget::pixelWidth() const +{ + return msi.pixelWidth(); +} + +const Rect KigWidget::fromScreen( const QRect& r ) +{ + return msi.fromScreen( r ); +} + + +void KigWidget::updateScrollBars() +{ + mview->updateScrollBars(); +} + +KigView::KigView( KigPart* part, + bool fullscreen, + QWidget* parent, + const char* name ) + : QWidget( parent, name ), + mlayout( 0 ), mrightscroll( 0 ), mbottomscroll( 0 ), + mupdatingscrollbars( false ), + mrealwidget( 0 ), mpart( part ) +{ + connect( part, SIGNAL( recenterScreen() ), this, SLOT( slotInternalRecenterScreen() ) ); + + mlayout = new QGridLayout( this, 2, 2 ); + mrightscroll = new QScrollBar( Vertical, this, "Right Scrollbar" ); + // TODO: make this configurable... + mrightscroll->setTracking( true ); + connect( mrightscroll, SIGNAL( valueChanged( int ) ), + this, SLOT( slotRightScrollValueChanged( int ) ) ); + connect( mrightscroll, SIGNAL( sliderReleased() ), + this, SLOT( updateScrollBars() ) ); + mbottomscroll = new QScrollBar( Horizontal, this, "Bottom Scrollbar" ); + connect( mbottomscroll, SIGNAL( valueChanged( int ) ), + this, SLOT( slotBottomScrollValueChanged( int ) ) ); + connect( mbottomscroll, SIGNAL( sliderReleased() ), + this, SLOT( updateScrollBars() ) ); + mrealwidget = new KigWidget( part, this, this, "Kig Widget", fullscreen ); + mlayout->addWidget( mbottomscroll, 1, 0 ); + mlayout->addWidget( mrealwidget, 0, 0 ); + mlayout->addWidget( mrightscroll, 0, 1 ); + + resize( sizeHint() ); + mrealwidget->recenterScreen(); + part->redrawScreen( mrealwidget ); + updateScrollBars(); +} + +void KigView::updateScrollBars() +{ + // we update the scrollbars to reflect the new "total size" of the + // document... The total size is calced in entireDocumentRect(). + // ( it is calced as a rect that contains all the points in the + // document, and then enlarged a bit, and scaled to match the screen + // width/height ratio... + // What we do here is tell the scroll bars what they should show as + // their total size.. + + // see the doc of this variable in the header for this... + mupdatingscrollbars = true; + + Rect er = mrealwidget->entireDocumentRect(); + Rect sr = mrealwidget->screenInfo().shownRect(); + + // we define the total rect to be the smallest rect that contains + // both er and sr... + er |= sr; + + // we need ints, not doubles, so since "pixelwidth == widgetcoord / + // internalcoord", we use "widgetcoord/pixelwidth", which would then + // equal "internalcoord", which has to be an int ( by definition.. ) + // i know, i'm a freak to think about these sorts of things... ;) + double pw = mrealwidget->screenInfo().pixelWidth(); + + // what the scrollbars reflect is the bottom resp. the left side of + // the shown rect. This is why the maximum value is not er.top() + // (which would be the maximum value of the top of the shownRect), + // but er.top() - sr.height(), which is the maximum value the bottom of + // the shownRect can reach... + + int rightmin = static_cast<int>( er.bottom() / pw ); + int rightmax = static_cast<int>( ( er.top() - sr.height() ) / pw ); + + mrightscroll->setMinValue( rightmin ); + mrightscroll->setMaxValue( rightmax ); + mrightscroll->setLineStep( (int)( sr.height() / pw / 10 ) ); + mrightscroll->setPageStep( (int)( sr.height() / pw / 1.2 ) ); + + // note that since Qt has a coordinate system with the lowest y + // values at the top, and we have it the other way around ( i know i + // shouldn't have done this.. :( ), we invert the value that the + // scrollbar shows. This is inverted again in + // slotRightScrollValueChanged()... + mrightscroll->setValue( (int) ( rightmin + ( rightmax - ( sr.bottom() / pw ) ) ) ); + + mbottomscroll->setMinValue( (int)( er.left() / pw ) ); + mbottomscroll->setMaxValue( (int)( ( er.right() - sr.width() ) / pw ) ); + mbottomscroll->setLineStep( (int)( sr.width() / pw / 10 ) ); + mbottomscroll->setPageStep( (int)( sr.width() / pw / 1.2 ) ); + mbottomscroll->setValue( (int)( sr.left() / pw ) ); + + mupdatingscrollbars = false; +} + +Rect KigWidget::entireDocumentRect() const +{ + return matchScreenShape( mpart->document().suggestedRect() ); +} + +void KigView::slotRightScrollValueChanged( int v ) +{ + if ( ! mupdatingscrollbars ) + { + // we invert the inversion that was done in updateScrollBars() ( + // check the documentation there..; ) + v = mrightscroll->minValue() + ( mrightscroll->maxValue() - v ); + double pw = mrealwidget->screenInfo().pixelWidth(); + double nb = double( v ) * pw; + mrealwidget->scrollSetBottom( nb ); + }; +} + +void KigView::slotBottomScrollValueChanged( int v ) +{ + if ( ! mupdatingscrollbars ) + { + double pw = mrealwidget->screenInfo().pixelWidth(); + double nl = double( v ) * pw; + mrealwidget->scrollSetLeft( nl ); + }; +} + +void KigWidget::scrollSetBottom( double rhs ) +{ + Rect sr = msi.shownRect(); + Coordinate bl = sr.bottomLeft(); + bl.y = rhs; + sr.setBottomLeft( bl ); + msi.setShownRect( sr ); + mpart->redrawScreen( this ); +} + +void KigWidget::scrollSetLeft( double rhs ) +{ + Rect sr = msi.shownRect(); + Coordinate bl = sr.bottomLeft(); + bl.x = rhs; + sr.setBottomLeft( bl ); + msi.setShownRect( sr ); + mpart->redrawScreen( this ); +} + +const ScreenInfo& KigView::screenInfo() const +{ + return mrealwidget->screenInfo(); +} + +KigView::~KigView() +{ +} + +KigWidget* KigView::realWidget() const +{ + return mrealwidget; +} + +const KigDocument& KigWidget::document() const +{ + return mpart->document(); +} + +QSize KigWidget::sizeHint() const +{ + return QSize( 630, 450 ); +} + +void KigWidget::wheelEvent( QWheelEvent* e ) +{ + int delta = e->delta(); + Qt::Orientation orient = e->orientation(); + if ( orient == Qt::Vertical ) + mview->scrollVertical( delta ); + else + mview->scrollHorizontal( delta ); +} + +void KigView::scrollHorizontal( int delta ) +{ + if ( delta >= 0 ) + for ( int i = 0; i < delta; i += 120 ) + mbottomscroll->subtractLine(); + else + for ( int i = 0; i >= delta; i -= 120 ) + mbottomscroll->addLine(); +} + +void KigView::scrollVertical( int delta ) +{ + if ( delta >= 0 ) + for ( int i = 0; i < delta; i += 120 ) + mrightscroll->subtractLine(); + else + for ( int i = 0; i >= delta; i -= 120 ) + mrightscroll->addLine(); +} + +bool KigWidget::isFullScreen() const +{ + return misfullscreen; +} + +void KigView::slotZoomIn() +{ + mrealwidget->slotZoomIn(); +} + +void KigView::slotZoomOut() +{ + mrealwidget->slotZoomOut(); +} + +void KigWidget::slotRecenterScreen() +{ + Rect nr = mpart->document().suggestedRect(); + KigCommand* cd = + new KigCommand( *mpart, + i18n( "Recenter View" ) ); + + cd->addTask( new KigViewShownRectChangeTask( *this, nr ) ); + mpart->history()->addCommand( cd ); +} + +void KigView::toggleFullScreen() +{ + mrealwidget->setFullScreen( ! mrealwidget->isFullScreen() ); + if ( mrealwidget->isFullScreen() ) + topLevelWidget()->showFullScreen(); + else + topLevelWidget()->showNormal(); +} + +void KigWidget::setFullScreen( bool f ) +{ + misfullscreen = f; +} + +void KigWidget::zoomRect() +{ + mpart->emitStatusBarText( i18n( "Select the rectangle that should be shown." ) ); + DragRectMode d( *mpart, *this ); + mpart->runMode( &d ); + if ( ! d.cancelled() ) + { + Rect nr = d.rect(); + KigCommand* cd = + new KigCommand( *mpart, + i18n( "Change Shown Part of Screen" ) ); + + cd->addTask( new KigViewShownRectChangeTask( *this, nr ) ); + mpart->history()->addCommand( cd ); + }; + + mpart->redrawScreen( this ); + updateScrollBars(); +} + +void KigView::zoomRect() +{ + mrealwidget->zoomRect(); +} + +void KigWidget::setShowingRect( const Rect& r ) +{ + msi.setShownRect( r.matchShape( Rect::fromQRect( rect() ) ) ); +} + +void KigView::slotRecenterScreen() +{ + mrealwidget->slotRecenterScreen(); +} + +void KigView::slotInternalRecenterScreen() +{ + mrealwidget->recenterScreen(); +} + +void KigWidget::zoomArea() +{ +// mpart->emitStatusBarText( i18n( "Select the area that should be shown." ) ); + Rect oldrect = showingRect(); + Coordinate tl = oldrect.topLeft(); + Coordinate br = oldrect.bottomRight(); + bool ok = true; + KigInputDialog::getTwoCoordinates( i18n( "Select Zoom Area" ), + i18n( "Select the zoom area by entering the coordinates of " + "the upper left corner and the lower right corner." ) + + QString::fromLatin1("<br>") + + mpart->document().coordinateSystem().coordinateFormatNoticeMarkup(), + this, &ok, mpart->document(), &tl, &br ); + if ( ok ) + { + Coordinate nc1( tl.x, br.y ); + Coordinate nc2( br.x, tl.y ); + Rect nr( nc1, nc2 ); + KigCommand* cd = new KigCommand( *mpart, i18n( "Change Shown Part of Screen" ) ); + + cd->addTask( new KigViewShownRectChangeTask( *this, nr ) ); + mpart->history()->addCommand( cd ); + } + + mpart->redrawScreen( this ); + updateScrollBars(); +} + +void KigView::zoomArea() +{ + mrealwidget->zoomArea(); +} + diff --git a/kig/kig/kig_view.h b/kig/kig/kig_view.h new file mode 100644 index 00000000..7970e088 --- /dev/null +++ b/kig/kig/kig_view.h @@ -0,0 +1,274 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + + +#ifndef KIG_VIEW_H +#define KIG_VIEW_H + +#include <qwidget.h> +#include <qpixmap.h> + +#include <kparts/part.h> + +#include <vector> + +#include "../objects/object_holder.h" +#include "../misc/rect.h" +#include "../misc/screeninfo.h" + +class QGridLayout; +class QScrollBar; + +class KigDocument; +class KigView; + +/** + * This class is the real widget showing the document. The other is a + * wrapper, that has the scrollbars... I'm not using QScrollView + * cause i've been having problems with that, and it's easier to do + * the work myself... + * Internally, this is basically a dumb class, which is manipulated by + * KigMode's. All events are forwarded to them. + */ +class KigWidget : public QWidget +{ + Q_OBJECT + + KigPart* mpart; + KigView* mview; + + // we reimplement these from QWidget to suit our needs + void mousePressEvent( QMouseEvent* e ); + void mouseMoveEvent( QMouseEvent* e ); + void mouseReleaseEvent( QMouseEvent* e ); + void paintEvent( QPaintEvent* e ); + void wheelEvent( QWheelEvent* e ); + void resizeEvent( QResizeEvent* ); + QSize sizeHint() const; + + /** + * this is called to match a rect's dimensions to the dimensions of + * the window before we set mViewRect to it. This is done cause we + * always want circles to look like circles etc... + */ + Rect matchScreenShape( const Rect& r ) const; + +public: + /** + * what do the still objects look like + * wondering if this is appropriate, maybe it should be part of + * MovingMode ? + */ + QPixmap stillPix; + /** + * temporary, gets bitBlt'd (copied) onto the widget + * (to avoid flickering) + */ + QPixmap curPix; + +protected: + std::vector<QRect> oldOverlay; + + /** + * this is a class that maps from our widget coordinates to the + * document's coordinates ( and back ). + */ + ScreenInfo msi; + + /** + * is this a full-screen widget ? + */ + bool misfullscreen; + +public: + /** + * standard qwidget constructor. if fullscreen is true, we're a + * fullscreen widget. + */ + KigWidget( KigPart* doc, + KigView* view, + QWidget* parent = 0, + const char* name = 0, + bool fullscreen = false + ); + ~KigWidget(); + + bool isFullScreen() const; + void setFullScreen( bool f ); + + const KigView* view() const { + return mview; + } + + KigView* view() { + return mview; + } + + /** + * The following are functions used by KigMode's to tell us to draw + * stuff... + * i tried to optimise the drawing as much as possible, using + * much ideas from kgeo + * DOUBLE BUFFERING: + * we don't draw on the widget directly, we draw on a QPixmap ( + * curPix ), and bitBlt that onto the widget to avoid flickering. + * TRIPLE BUFFERING: + * we also currently keep an extra pixmap of what the widget looks + * like without objects that are moving... i'm currently wondering + * whether this isn't a performance loss rather than a gain, but + * well, i haven't done any measurements (yet ?), so for now it + * stays in... + * OVERLAYS + * Another thing: it turns out that working on the pixmaps isn't + * that slow, but working on the widget is. So we try to reduce the + * amount of work we spend on the widget. (i got this idea from + * kgeo, all credits for this go to marc.bartsch@web.de) + * on drawing, KigPainter tells us (appendOverlay) for everything it + * draws what rects it draws in, so we know on updating the widget ( + * updateWidget() that the rest is still ok and doesn't need to be + * bitBlt'd again on the widget... + */ + + /** + * clear stillPix... + */ + void clearStillPix(); + /** + * update curPix (bitBlt stillPix onto curPix..) + */ + void updateCurPix( const std::vector<QRect>& = std::vector<QRect>()); + + /** + * this means bitBlting curPix on the actual widget... + */ + void updateWidget( const std::vector<QRect>& = std::vector<QRect>() ); + void updateEntireWidget(); + + /** + * Mapping between Internal Coordinate Systems + * there are two coordinate systems: + * 1 the widget's coordinates: these are simple int's from (0,0) in + * the topleft of the widget to size() in the bottomRight... + * 2 the document's coordinates: these are the coordinates used by + * the KigDocument. Objects only know of their coordinates as + * related to this system. + * These are mapped by the KigView using the ScreenInfo class. + */ + const Rect showingRect() const; + void setShowingRect( const Rect& r ); + + const Coordinate fromScreen( const QPoint& p ); + const Rect fromScreen( const QRect& r ); + double pixelWidth() const; + + /** + * the part of the document we're currently showing + * i.e. a rectangle of the document (which has its own coordinate + * system) which is mapped onto the widget. + */ + const ScreenInfo& screenInfo() const; + + Rect entireDocumentRect() const; + + void updateScrollBars(); + + void scrollSetBottom( double rhs ); + void scrollSetLeft( double rhs ); + + const KigDocument& document() const; + +public: + /** + * this recenters the screen, that is, resets the shown rect to + * mpart->document().suggestedRect().. + */ + void recenterScreen(); + /** + * this gets called if the user clicks the recenter screen button. + * It adds a KigCommand to the CommandHistory that recenters the + * screen.. + */ + void slotRecenterScreen(); + + // called when the user clicks the appropriate buttons.. + void slotZoomIn(); + void slotZoomOut(); + + void zoomRect(); + void zoomArea(); + + void redrawScreen( const std::vector<ObjectHolder*>& selection, bool paintOnWidget = true ); +}; + +/** + * This class is a wrapper for KigWidget. It has some actions + * that belong here, and not in the part. It also maintains the + * scrollbars, but it doesn't manipulate them itself. It forwards + * most of its functionality to KigWidget... + */ +class KigView + : public QWidget +{ + Q_OBJECT + + QGridLayout* mlayout; + QScrollBar* mrightscroll; + QScrollBar* mbottomscroll; + + /** + * apparently, QScrollBar also emits its signals when you update it + * manually, so we ignore them while we're in \ref updateScrollBars()... + */ + bool mupdatingscrollbars; + + KigWidget* mrealwidget; + KigPart* mpart; + +public: + KigView( KigPart* part, + bool fullscreen = false, + QWidget* parent = 0, + const char* name = 0 + ); + ~KigView(); + + void setupActions(); + + const ScreenInfo& screenInfo() const; + + KigWidget* realWidget() const; + void scrollHorizontal( int delta ); + void scrollVertical( int delta ); + +public slots: + void updateScrollBars(); + void slotZoomIn(); + void slotZoomOut(); + void zoomRect(); + void zoomArea(); + void slotInternalRecenterScreen(); + void slotRecenterScreen(); + void toggleFullScreen(); + +private slots: + void slotRightScrollValueChanged( int ); + void slotBottomScrollValueChanged( int ); +}; +#endif diff --git a/kig/kig/kigpartui.rc b/kig/kig/kigpartui.rc new file mode 100644 index 00000000..7e594416 --- /dev/null +++ b/kig/kig/kigpartui.rc @@ -0,0 +1,288 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="kig_part" version="10"> + <MenuBar> + <Menu name="file"> + <text>&File</text> + <Action name="file_save" /> + <Action name="file_save_as" /> + <Separator /> + <Action name="file_print" /> + <Action name="file_print_preview" /> + <Separator /> + <Action name="file_export" /> + <Separator /> + </Menu> + <Menu name="edit"> + <text>&Edit</text> + <Action name="edit_undo" /> + <Action name="edit_redo" /> + <Separator /> + <Action name="edit_select_all" /> + <Action name="edit_deselect" /> + <Action name="edit_invert_selection" /> + <Separator/> + <Action name="edit_unhide_all" /> + </Menu> + <Menu name="view"> + <text>&View</text> + <Action name="view_zoom_in" /> + <Action name="view_zoom_out" /> + <Action name="view_fit_to_page" /> + <Action name="view_select_shown_rect" /> + <Action name="view_zoom_area" /> + </Menu> + <Menu name="objects"> + <text>&Objects</text> + <Menu name="new_point" icon="point"> + <text>&Points</text> + <Action name="objects_new_normalpoint" /> + <Action name="objects_new_midpoint" /> + <Action name="objects_new_intersection" /> + <Action name="objects_new_point_xy" /> + <Action name="objects_new_translatedpoint" /> + <Action name="objects_new_rotatedpoint" /> + <Action name="objects_new_mirrorpoint" /> + <ActionList name="user_point_types" /> + </Menu> + <Menu name="new_line" icon="line"> + <text>&Lines</text> + <Action name="objects_new_linettp" /> + <Action name="objects_new_lineperpend" /> + <Action name="objects_new_lineparallel" /> + <Action name="objects_new_ray" /> + <Action name="objects_new_linebyvector" /> + <Action name="objects_new_halflinebyvector" /> + <ActionList name="user_line_types" /> + </Menu> + <Menu name="new_circle" icon="circlebps"> + <text>&Circles && Arcs</text> + <Action name="objects_new_circlebcp" /> + <Action name="objects_new_circlebtp" /> + <Action name="objects_new_circlebps" /> + <Action name="objects_new_circlebpd" /> + <Action name="objects_new_circlebcl" /> + <Action name="objects_new_arcbtp" /> + <Action name="objects_new_arcbcpa" /> + <ActionList name="user_circle_types" /> + </Menu> + <Menu name="new_poligon" icon="hexagonbcv"> + <text>Poly&gons</text> + <Action name="objects_new_trianglebtp" /> + <Action name="objects_new_polygonbnp" /> + <Action name="objects_new_polygonbcv" /> + <Action name="objects_new_equitriangle" /> + <Action name="objects_new_square" /> + <Action name="objects_new_polygonvertices" /> + <Action name="objects_new_polygonsides" /> + <Action name="objects_new_convexhull" /> + </Menu> + <Menu name="new_vector" icon="vector"> + <text>&Vectors && Segments</text> + <Action name="objects_new_segment" /> + <Action name="objects_new_segment_axis" /> + <Action name="objects_new_vector" /> + <Action name="objects_new_vectorsum" /> + <Action name="objects_new_vectordifference" /> + <ActionList name="user_segment_types" /> + </Menu> + <Menu name="new_conic" icon="conicb5p"> + <text>Co&nics && Cubics</text> + <Action name="objects_new_ellipsebffp" /> + <Action name="objects_new_hyperbolabffp" /> + <Action name="objects_new_conicb5p" /> + <Action name="objects_new_parabolabtp" /> + <ActionList name="user_conic_types" /> + <Menu name="new_moreconics" icon="conicsradicalline"> + <text>More Conics</text> + <Action name="objects_new_parabolabdp" /> + <Action name="objects_new_equilateralhyperbolab4p" /> + <Action name="objects_new_conicbdfp" /> + <Action name="objects_new_conicbaap" /> + <Action name="objects_new_linepolar" /> + <Action name="objects_new_lineconicasymptotes" /> + <Action name="objects_new_pointpolar" /> + <Action name="objects_new_linedirectrix" /> + <Action name="objects_new_lineconicradical" /> + </Menu> + <Separator /> + <Menu name="new_cubic"> + <text>Cu&bics</text> + <Action name="objects_new_cubicb9p" /> + <Action name="objects_new_cubicnodeb6p" /> + <Action name="objects_new_cubiccuspb4p" /> + </Menu> + </Menu> + <Menu name="new_angle" icon="angle"> + <text>&Angles</text> + <Action name="objects_new_angle" /> + <Action name="objects_new_angle_bisector" /> + </Menu> + <Menu name="new_transformation" icon="centralsymmetry"> + <text>&Transformations</text> + <Action name="objects_new_translation" /> + <Action name="objects_new_pointreflection" /> + <Action name="objects_new_linereflection" /> + <Action name="objects_new_rotation" /> + <Action name="objects_new_scalingovercenter" /> + <Action name="objects_new_scalingovercenter2" /> + <Action name="objects_new_scalingoverline" /> + <Action name="objects_new_scalingoverline2" /> + <Action name="objects_new_similitude" /> + <Action name="objects_new_inversion" /> + <Action name="objects_new_harmonichomology" /> + <Action name="objects_new_genericaffinity" /> + <Action name="objects_new_genericprojectivity" /> + <Action name="objects_new_castshadow" /> + <Action name="objects_new_projectiverotation" /> + </Menu> + <Menu name="new_differentialgeometry" icon="tangent"> + <text>&Differential geometry</text> + <Action name="objects_new_tangent" /> + <Action name="objects_new_centerofcurvature" /> + <Action name="objects_new_osculatingcircle" /> + <Action name="objects_new_evolute" /> + </Menu> + <Menu name="new_test" icon="test"> + <text>T&ests</text> + <Action name="objects_new_areparallel" /> + <Action name="objects_new_areorthogonal" /> + <Action name="objects_new_arecollinear" /> + <Action name="objects_new_containstest" /> + <Action name="objects_new_distancetest" /> + <Action name="objects_new_vectorequalitytest" /> + <Action name="objects_new_inpolygontest" /> + <Action name="objects_new_convexpolygontest" /> + </Menu> + <Menu name="new_other"> + <text>&Other</text> + <Action name="objects_new_locus" /> + <Action name="objects_new_textlabel" /> + <Action name="objects_new_measuretransport" /> + <Action name="objects_new_script_python" /> + <ActionList name="user_other_types" /> + </Menu> + <Separator /> + <Action name="delete_objects" /> + <Action name="cancel_construction" /> + </Menu> + <Menu name="types"> + <text>&Types</text> + <Action name="macro_action" /> + <Action name="types_edit" /> + </Menu> + <Menu name="settings"> + <Action name="fullscreen" /> + <Action name="settings_set_coordinate_system" /> + <Action name="settings_show_grid" /> + <Action name="settings_show_axes" /> + <Action name="settings_toggle_nightvision" /> + </Menu> + </MenuBar> + <ToolBar name="mainToolBar"> + <text>Main Toolbar</text> + <Action name="file_save" /> + <Action name="file_save_as" /> + <Separator /> + <Action name="file_print" /> + <Separator /> + <Action name="edit_undo"/> + <Action name="edit_redo"/> + <Separator /> + <Action name="delete_objects"/> + <Action name="cancel_construction"/> + <Action name="macro_action"/> + </ToolBar> + <ToolBar name="points_toolbar" position="left"> + <text>Points</text> + <Action name="objects_new_normalpoint" /> + <Action name="objects_new_point_xy" /> + <Action name="objects_new_intersection" /> + <Action name="objects_new_midpoint" /> + <Action name="objects_new_mirrorpoint" /> + <Action name="objects_new_rotatedpoint" /> + <Action name="objects_new_translatedpoint" /> + <ActionList name="user_point_types" /> + </ToolBar> + <ToolBar name="line_toolbar" position="left"> + <text>Lines</text> + <Action name="objects_new_linettp" /> + <Action name="objects_new_ray" /> + <Action name="objects_new_lineperpend" /> + <Action name="objects_new_lineparallel" /> + <Action name="objects_new_linebyvector" /> + <Action name="objects_new_halflinebyvector" /> + <ActionList name="user_line_types" /> + </ToolBar> + <ToolBar name="vectseg_toolbar" position="left"> + <text>Vectors && Segments</text> + <Action name="objects_new_segment" /> + <Action name="objects_new_segment_axis" /> + <Action name="objects_new_vector" /> + <Action name="objects_new_vectorsum" /> + <ActionList name="user_segment_types" /> + </ToolBar> + <ToolBar name="circle_toolbar" position="left"> + <text>Circles && Arcs</text> + <Action name="objects_new_circlebcp" /> + <Action name="objects_new_circlebtp" /> + <Action name="objects_new_circlebps" /> + <Action name="objects_new_circlebpd" /> + <Action name="objects_new_arcbtp" /> + <ActionList name="user_circle_types" /> + </ToolBar> + <ToolBar name="conic_toolbar" position="left"> + <text>Conics</text> + <Action name="objects_new_ellipsebffp" /> + <Action name="objects_new_hyperbolabffp" /> + <Action name="objects_new_parabolabtp" /> + <Action name="objects_new_conicb5p" /> + <ActionList name="user_conic_types" /> + <Action name="objects_new_lineconicradical" /> + </ToolBar> + <ToolBar name="angles_toolbar" position="left"> + <text>Angles</text> + <Action name="objects_new_angle" /> + <Action name="objects_new_angle_bisector" /> + </ToolBar> + <ToolBar name="transformation_toolbar" position="right"> + <text>Transformations</text> + <Action name="objects_new_translation" /> + <Action name="objects_new_pointreflection" /> + <Action name="objects_new_linereflection" /> + <Action name="objects_new_rotation" /> + <Action name="objects_new_scalingovercenter" /> + <Action name="objects_new_scalingoverline" /> + <Action name="objects_new_similitude" /> + <Action name="objects_new_inversion" /> + <Action name="objects_new_harmonichomology" /> + <Action name="objects_new_genericaffinity" /> + <Action name="objects_new_genericprojectivity" /> + </ToolBar> + <ToolBar name="tests_toolbar" position="right"> + <text>Tests</text> + <Action name="objects_new_areparallel" /> + <Action name="objects_new_areorthogonal" /> + <Action name="objects_new_arecollinear" /> + <Action name="objects_new_containstest" /> + <Action name="objects_new_distancetest" /> + <Action name="objects_new_vectorequalitytest" /> + <Action name="objects_new_inpolygontest" /> + <Action name="objects_new_convexpolygontest" /> + </ToolBar> + <ToolBar name="rest_toolbar" position="left"> + <text>Other Objects</text> + <Action name="objects_new_locus" /> + <Action name="objects_new_textlabel" /> + <Action name="objects_new_script_python" /> + <ActionList name="user_other_types" /> + </ToolBar> + <ToolBar name="view_toolbar"> + <text>View</text> + <Action name="view_zoom_in" /> + <Action name="view_zoom_out" /> + <Action name="fullscreen" /> + <Action name="view_fit_to_page" /> + <Action name="view_select_shown_rect" /> + <Action name="view_zoom_area" /> + </ToolBar> +</kpartgui> diff --git a/kig/kig/kigui.rc b/kig/kig/kigui.rc new file mode 100644 index 00000000..db90b0d2 --- /dev/null +++ b/kig/kig/kigui.rc @@ -0,0 +1,40 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="kig_shell" version="3"> +<MenuBar> + <Menu name="file" noMerge="1"><text>&File</text> + <Action name="file_new"/> + <Action name="file_open"/> + <Action name="file_open_recent"/> + <Separator /> + <Merge /> + <Action name="file_quit"/> + </Menu> + <Merge /> + <Menu name="settings" noMerge="1"><text>&Settings</text> + <Action name="options_show_toolbar"/> + <Merge name="StandardToolBarMenuHandler" /> + <Action name="options_show_statusbar"/> + <Merge /> + <Separator/> + <Action name="options_configure_keybinding"/> + <Action name="options_configure_toolbars"/> + </Menu> + <Menu name="help" noMerge="1"><text>&Help</text> + <Action name="help_contents"/> + <Action name="help_whats_this"/> + <Separator/> + <Action name="help_tipofday"/> + <Separator/> + <Action name="help_report_bug"/> + <Separator/> + <Action name="help_about_app"/> + <Action name="help_about_kde"/> + </Menu> +</MenuBar> +<ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text> + <Action name="file_new"/> + <Action name="file_open"/> + <Separator/> + <Merge /> +</ToolBar> +</kpartgui> diff --git a/kig/kig/main.cpp b/kig/kig/main.cpp new file mode 100644 index 00000000..d0a70404 --- /dev/null +++ b/kig/kig/main.cpp @@ -0,0 +1,144 @@ +/** + This file is part of Kig, a KDE program for Interactive Geometry... + Copyright (C) 2002 Dominique Devriese <devriese@kde.org> + + 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. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + +#include "kig.h" + +#include <kuniqueapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <klocale.h> +#include <klibloader.h> +#include <kdebug.h> + +#include "aboutdata.h" + +static KCmdLineOptions options[] = + { + { "c", 0, 0 }, + { "convert-to-native", I18N_NOOP( "Do not show a GUI. Convert the specified file to the native Kig format. Output goes to stdout unless --outfile is specified." ), 0 }, + { "o", 0, 0 }, + { "outfile <file>", I18N_NOOP( "File to output the created native file to. '-' means output to stdout. Default is stdout as well." ), 0 }, + { "+[URL]", I18N_NOOP( "Document to open" ), 0 }, + KCmdLineLastOption + }; + +class KigApplication + : public KUniqueApplication +{ +public: + KigApplication( bool gui = true ); + int newInstance(); + void handleArgs( KCmdLineArgs* args ); +}; + +KigApplication::KigApplication( bool gui ) + : KUniqueApplication( gui, gui ) +{ +} + +int KigApplication::newInstance() +{ + static bool first = true; + if (isRestored() && first) + { + first = false; + return 0; + } + first = false; + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + handleArgs(args); + args->clear(); + return 0; +} + +void KigApplication::handleArgs( KCmdLineArgs* args ) +{ + if ( args->count() == 0 ) + { + Kig *widget = new Kig; + widget->show(); + } + else + { + for (int i = 0; i < args->count(); i++ ) + { + Kig *widget = new Kig; + widget->show(); + widget->load( args->url( i ) ); + } + } +} + +static int convertToNative( const KURL& file, const QCString& outfile ) +{ + KigApplication app( false ); + KLibrary* library = KLibLoader::self()->globalLibrary( "libkigpart" ); + int ( *converterfunction )( const KURL&, const QCString& ); + converterfunction = ( int ( * )( const KURL&, const QCString& ) ) library->symbol( "convertToNative" ); + if ( !converterfunction ) + { + kdError() << "Error: broken Kig installation: different library and application version !" << endl; + return -1; + } + return (*converterfunction)( file, outfile ); +} + +int main(int argc, char **argv) +{ + KAboutData *about = kigAboutData( "kig", I18N_NOOP("Kig") ); + + KCmdLineArgs::init(argc, argv, about); + KCmdLineArgs::addCmdLineOptions( options ); + KigApplication::addCmdLineOptions(); + + KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); + if ( args->isSet( "convert-to-native" ) ) + { + QCString outfile = args->getOption( "outfile" ); + if ( outfile.isNull() ) + outfile = "-"; + + if ( args->count() == 0 ) + { + kdError() << "Error: --convert-to-native specified without a file to convert." << endl; + return -1; + } + if ( args->count() > 1 ) + { + kdError() << "Error: --convert-to-native specified with more than one file to convert." << endl; + return -1; + } + return convertToNative( args->url( 0 ), outfile ); + } + else + { + if ( args->isSet( "outfile" ) ) + { + kdError() << "Error: --outfile specified without convert-to-native." << endl; + return -1; + } + KigApplication app; + + // see if we are starting with session management + if (app.isRestored()) RESTORE(Kig) + return app.exec(); + } +} |