
* graphicsview.cpp: Add the possibility to scale the scene with the wheel and CTRL + or -. Not completely finished, * graphicsview.h, * scene.cpp: Correct the selection: she is not visible until there is an item in the scene. It is to avoid the fact that the scene take the selection rect when we select in an empty scene, * mainwindow.cpp: Create the menu bar and connect actions. For the most important : add File menu and Areas menu (handle visibility of dock widgets). --- GScribo/GScribo.pro | 11 ++- GScribo/GScribo.pro.user | 70 +++++++++++++++---- GScribo/Rendering/graphicsview.cpp | 74 +++++++++++++++++--- GScribo/Rendering/graphicsview.h | 23 +++++- GScribo/Rendering/regionitem.h | 4 +- GScribo/Rendering/scene.cpp | 33 ++++++--- GScribo/Rendering/scene.h | 7 ++- GScribo/Rendering/selection.cpp | 4 +- GScribo/TODO | 30 +++++++- GScribo/XmlWidget/xmlwidget.h | 4 +- GScribo/aboutdialog.h | 24 ++++++ GScribo/aboutdialog.ui | 136 ++++++++++++++++++++++++++++++++++++ GScribo/dockwidget.h | 22 ++++++ GScribo/graphicswidget.h | 18 +++++ GScribo/helpdialog.cpp | 1 + GScribo/mainwindow.cpp | 41 +++++++++++ GScribo/mainwindow.h | 13 ++-- Test2/l.txt | 1 + 18 files changed, 456 insertions(+), 60 deletions(-) create mode 100644 GScribo/aboutdialog.h create mode 100644 GScribo/aboutdialog.ui create mode 100644 GScribo/dockwidget.h create mode 100644 GScribo/graphicswidget.h create mode 100644 GScribo/helpdialog.cpp create mode 100644 Test2/l.txt diff --git a/GScribo/GScribo.pro b/GScribo/GScribo.pro index c5613f6..a80da2d 100644 --- a/GScribo/GScribo.pro +++ b/GScribo/GScribo.pro @@ -11,8 +11,9 @@ LIBS += -I/usr/include/graphicsImage \ -ltesseract_full TARGET = GScribo TEMPLATE = app -SOURCES += main.cpp \ +SOURCES += regionwidget.cpp \ mainwindow.cpp \ + main.cpp \ xml.cpp \ Rendering/scene.cpp \ Rendering/selection.cpp \ @@ -32,10 +33,11 @@ SOURCES += main.cpp \ XmlWidget/xmlitem.cpp \ XmlWidget/xmlattributes.cpp \ XmlWidget/attributesmodel.cpp \ - XmlWidget/xmlview.cpp \ - regionwidget.cpp + XmlWidget/xmlview.cpp HEADERS += mainwindow.h \ variantpointer.h \ + regionwidget.h \ + aboutdialog.h \ configs.h \ region.h \ dir.h \ @@ -63,8 +65,9 @@ HEADERS += mainwindow.h \ PagesWidget/pagesdelegate.h \ Rendering/rootgraphicsitem.h \ XmlWidget/xmlview.h \ - regionwidget.h + dockwidget.h FORMS += mainwindow.ui \ + aboutdialog.ui \ Preferences/preferencesdialog.ui \ Preferences/ocroptions.ui \ Preferences/segmentationoptions.ui \ diff --git a/GScribo/GScribo.pro.user b/GScribo/GScribo.pro.user index 0274cef..dce13f4 100644 --- a/GScribo/GScribo.pro.user +++ b/GScribo/GScribo.pro.user @@ -76,7 +76,7 @@ <valuemap type="QVariantMap"> <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Debug</value> <valuelist key="abstractProcess.Environment" type="QVariantList"> - <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-MYegNG7MAz,guid=fddbeed997eaec30b39f769300000038</value> + <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-e8Ai0asIF8,guid=40cd8e30a2205708b63bff1e00011544</value> <value type="QString">DESKTOP_SESSION=fluxbox</value> <value type="QString">DISPLAY=:0.0</value> <value type="QString">GDMSESSION=fluxbox</value> @@ -85,6 +85,7 @@ <value type="QString">GTK_MODULES=canberra-gtk-module</value> <value type="QString">HOME=/lrde/home/stage/froger_a</value> <value type="QString">LANG=fr_FR.UTF-8</value> + <value type="QString">LANGUAGE=</value> <value type="QString">LD_LIBRARY_PATH=/usr/lib/qtcreator</value> <value type="QString">LOGNAME=froger_a</value> <value type="QString">PATH=/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/games</value> @@ -92,16 +93,16 @@ <value type="QString">QTDIR=/usr/share/qt4</value> <value type="QString">SHELL=/bin/bash</value> <value type="QString">SHLVL=2</value> - <value type="QString">SSH_AGENT_PID=2086</value> - <value type="QString">SSH_AUTH_SOCK=/tmp/ssh-hPSRAn2025/agent.2025</value> + <value type="QString">SSH_AGENT_PID=8827</value> + <value type="QString">SSH_AUTH_SOCK=/tmp/ssh-zNmFSg8766/agent.8766</value> <value type="QString">TERM=xterm</value> <value type="QString">USER=froger_a</value> <value type="QString">USERNAME=froger_a</value> - <value type="QString">WINDOWID=16777240</value> - <value type="QString">WINDOWPATH=7</value> - <value type="QString">XAUTHORITY=/tmp/.gdmC10ASW</value> + <value type="QString">WINDOWID=10485784</value> + <value type="QString">WINDOWPATH=7:8:8</value> + <value type="QString">XAUTHORITY=/tmp/.gdm1MPCSW</value> <value type="QString">XDG_DATA_DIRS=/usr/local/share/:/usr/share/:/usr/share/gdm/</value> - <value type="QString">XDG_SESSION_COOKIE=9a5c41ad78622411b8e25b00459a554f-1360774468.168232-1277165267</value> + <value type="QString">XDG_SESSION_COOKIE=9a5c41ad78622411b8e25b00459a554f-1360845394.397476-591106291</value> <value type="QString">XTERM_LOCALE=fr_FR.UTF-8</value> <value type="QString">XTERM_SHELL=/bin/bash</value> <value type="QString">XTERM_VERSION=XTerm(261)</value> @@ -123,7 +124,7 @@ <valuemap type="QVariantMap"> <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Debug</value> <valuelist key="abstractProcess.Environment" type="QVariantList"> - <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-MYegNG7MAz,guid=fddbeed997eaec30b39f769300000038</value> + <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-e8Ai0asIF8,guid=40cd8e30a2205708b63bff1e00011544</value> <value type="QString">DESKTOP_SESSION=fluxbox</value> <value type="QString">DISPLAY=:0.0</value> <value type="QString">GDMSESSION=fluxbox</value> @@ -132,6 +133,7 @@ <value type="QString">GTK_MODULES=canberra-gtk-module</value> <value type="QString">HOME=/lrde/home/stage/froger_a</value> <value type="QString">LANG=fr_FR.UTF-8</value> + <value type="QString">LANGUAGE=</value> <value type="QString">LD_LIBRARY_PATH=/usr/lib/qtcreator</value> <value type="QString">LOGNAME=froger_a</value> <value type="QString">PATH=/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/games</value> @@ -139,16 +141,16 @@ <value type="QString">QTDIR=/usr/share/qt4</value> <value type="QString">SHELL=/bin/bash</value> <value type="QString">SHLVL=2</value> - <value type="QString">SSH_AGENT_PID=2086</value> - <value type="QString">SSH_AUTH_SOCK=/tmp/ssh-hPSRAn2025/agent.2025</value> + <value type="QString">SSH_AGENT_PID=8827</value> + <value type="QString">SSH_AUTH_SOCK=/tmp/ssh-zNmFSg8766/agent.8766</value> <value type="QString">TERM=xterm</value> <value type="QString">USER=froger_a</value> <value type="QString">USERNAME=froger_a</value> - <value type="QString">WINDOWID=16777240</value> - <value type="QString">WINDOWPATH=7</value> - <value type="QString">XAUTHORITY=/tmp/.gdmC10ASW</value> + <value type="QString">WINDOWID=10485784</value> + <value type="QString">WINDOWPATH=7:8:8</value> + <value type="QString">XAUTHORITY=/tmp/.gdm1MPCSW</value> <value type="QString">XDG_DATA_DIRS=/usr/local/share/:/usr/share/:/usr/share/gdm/</value> - <value type="QString">XDG_SESSION_COOKIE=9a5c41ad78622411b8e25b00459a554f-1360774468.168232-1277165267</value> + <value type="QString">XDG_SESSION_COOKIE=9a5c41ad78622411b8e25b00459a554f-1360845394.397476-591106291</value> <value type="QString">XTERM_LOCALE=fr_FR.UTF-8</value> <value type="QString">XTERM_SHELL=/bin/bash</value> <value type="QString">XTERM_VERSION=XTerm(261)</value> @@ -166,6 +168,46 @@ <variable>buildconfiguration-Debug-cleanstep0</variable> <valuemap type="QVariantMap"> <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Debug</value> + <valuelist key="abstractProcess.Environment" type="QVariantList"> + <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-e8Ai0asIF8,guid=40cd8e30a2205708b63bff1e00011544</value> + <value type="QString">DESKTOP_SESSION=fluxbox</value> + <value type="QString">DISPLAY=:0.0</value> + <value type="QString">GDMSESSION=fluxbox</value> + <value type="QString">GDM_LANG=fr_FR.UTF-8</value> + <value type="QString">GDM_XSERVER_LOCATION=local</value> + <value type="QString">GTK_MODULES=canberra-gtk-module</value> + <value type="QString">HOME=/lrde/home/stage/froger_a</value> + <value type="QString">LANG=fr_FR.UTF-8</value> + <value type="QString">LANGUAGE=</value> + <value type="QString">LD_LIBRARY_PATH=/usr/lib/qtcreator</value> + <value type="QString">LOGNAME=froger_a</value> + <value type="QString">PATH=/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/games</value> + <value type="QString">PWD=/lrde/home/stage/froger_a/qt/GScribo</value> + <value type="QString">QTDIR=/usr/share/qt4</value> + <value type="QString">SHELL=/bin/bash</value> + <value type="QString">SHLVL=2</value> + <value type="QString">SSH_AGENT_PID=8827</value> + <value type="QString">SSH_AUTH_SOCK=/tmp/ssh-zNmFSg8766/agent.8766</value> + <value type="QString">TERM=xterm</value> + <value type="QString">USER=froger_a</value> + <value type="QString">USERNAME=froger_a</value> + <value type="QString">WINDOWID=10485784</value> + <value type="QString">WINDOWPATH=7:8:8</value> + <value type="QString">XAUTHORITY=/tmp/.gdm1MPCSW</value> + <value type="QString">XDG_DATA_DIRS=/usr/local/share/:/usr/share/:/usr/share/gdm/</value> + <value type="QString">XDG_SESSION_COOKIE=9a5c41ad78622411b8e25b00459a554f-1360845394.397476-591106291</value> + <value type="QString">XTERM_LOCALE=fr_FR.UTF-8</value> + <value type="QString">XTERM_SHELL=/bin/bash</value> + <value type="QString">XTERM_VERSION=XTerm(261)</value> + </valuelist> + <value key="abstractProcess.IgnoreReturnValue" type="bool">true</value> + <valuelist key="abstractProcess.arguments" type="QVariantList"> + <value type="QString">clean</value> + <value type="QString">-w</value> + </valuelist> + <value key="abstractProcess.command" type="QString">/usr/bin/make</value> + <value key="abstractProcess.enabled" type="bool">true</value> + <value key="abstractProcess.workingDirectory" type="QString">/amd/nfs/volume1/home/stage/froger_a/qt/GScribo</value> <value key="cleanConfig" type="bool">true</value> <valuelist key="makeargs" type="QVariantList"> <value type="QString">clean</value> diff --git a/GScribo/Rendering/graphicsview.cpp b/GScribo/Rendering/graphicsview.cpp index 0068bfd..7ff083f 100644 --- a/GScribo/Rendering/graphicsview.cpp +++ b/GScribo/Rendering/graphicsview.cpp @@ -1,15 +1,23 @@ #include "graphicsview.h" +#include <QDebug> GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent) { - scaleRatio_ = 1; + init(); } GraphicsView::GraphicsView(QGraphicsScene *scene, QWidget *parent) : QGraphicsView(scene, parent) { + init(); +} + +void GraphicsView::init() +{ scaleRatio_ = 1; + setTransformationAnchor(GraphicsView::AnchorUnderMouse); + setBackgroundBrush(QBrush(Qt::lightGray)); } void GraphicsView::wheelEvent(QWheelEvent *event) @@ -17,15 +25,30 @@ void GraphicsView::wheelEvent(QWheelEvent *event) // Current wheel have an angle of 15 degrees by steps with a delta of + or - 120. A good scale is +- 0.1 in that case. // So we have to adapt for wheel whith better precision. - if((event->delta() > 0 && scaleRatio_ < 1.6) || (event->delta() < 0 && scaleRatio_ > 1)) + qreal degrees = 1 + static_cast<qreal>(event->delta()) / 1200; + //qDebug() << "Degrees : " << degrees; + qreal nextScaleRatio = scaleRatio_ * degrees; + //qDebug() << "Next Scale Ratio : " << nextScaleRatio; + if(event->delta() > 0) { - qreal degrees = static_cast<qreal>(event->delta()) / 1200; - scaleRatio_ += degrees; - degrees += 1; - scale(degrees, degrees); + if(nextScaleRatio <= 12) + { + scaleRatio_ = nextScaleRatio; + scale(degrees, degrees); + } + } + else + { + if(nextScaleRatio > 1) + { + scaleRatio_ = nextScaleRatio; + scale(degrees, degrees); + } + else if(scaleRatio_ != 1) + fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); } - QGraphicsView::wheelEvent(event); + //qDebug() << "Scale Ratio : " << scaleRatio_; } void GraphicsView::keyPressEvent(QKeyEvent* event) @@ -33,15 +56,15 @@ void GraphicsView::keyPressEvent(QKeyEvent* event) // Bitwise AND to check if at least CTRL is pushed. if(event->modifiers() & Qt::ControlModifier) { - if(event->key() == Qt::Key_Plus && scaleRatio_ < 1.5) + if(event->key() == Qt::Key_Plus && scaleRatio_ <= 11.8) { - scaleRatio_ += 0.2; + scaleRatio_ *= 1.2; scale(1.2, 1.2); } - else if(event->key() == Qt::Key_Minus && scaleRatio_ > 1) + else if(event->key() == Qt::Key_Minus && scaleRatio_ >= 1.2) { - scaleRatio_ -= 0.2; + scaleRatio_ *= 0.8; scale(0.8, 0.8); } } @@ -49,6 +72,7 @@ void GraphicsView::keyPressEvent(QKeyEvent* event) QGraphicsView::keyPressEvent(event); } +// When we fit an item or a rectangle in view (it's done each time a new picture is loaded), reinit the scale ratio. void GraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRadioMode) { scaleRatio_ = 1; @@ -66,3 +90,31 @@ void GraphicsView::fitInView(qreal x, qreal y, qreal w, qreal h, Qt::AspectRatio scaleRatio_ = 1; QGraphicsView::fitInView(x, y, w, h, aspectRadioMode); } + +void GraphicsView::resizeEvent(QResizeEvent *event) +{ + /*if(!isScalingScene) + { + qDebug() << event->oldSize(); + qDebug() << event->size(); + float ratio = static_cast<float>(event->size().width() * event->size().height()) / static_cast<float>(event->oldSize().width() * event->oldSize().height()); + + qDebug() << "Scale Ratio / Ratio : " << scaleRatio_ / ratio; + + // Check if the new geometry area is greater than the scene rect. + if(scaleRatio_ / ratio < 1) + fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); + else + { + scaleRatio_ *= ratio; + qDebug() << "Scale Ratio after minimi : " << scaleRatio_ * ratio; + } + + if(scaleRatio_ / ratio < 1) + fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); + } + isScalingScene = false;*/ + + //fitInView(scene()->sceneRect()); + QGraphicsView::resizeEvent(event); +} diff --git a/GScribo/Rendering/graphicsview.h b/GScribo/Rendering/graphicsview.h index 51f18dc..c546887 100644 --- a/GScribo/Rendering/graphicsview.h +++ b/GScribo/Rendering/graphicsview.h @@ -7,20 +7,35 @@ class GraphicsView : public QGraphicsView { + Q_OBJECT + public: explicit GraphicsView(QWidget *parent = 0); explicit GraphicsView(QGraphicsScene *scene, QWidget *parent = 0); - void fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRadioMode); - void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode); - void fitInView(qreal x, qreal y, qreal w, qreal h, Qt::AspectRatioMode aspectRadioMode); - protected: + void init(); + + void resizeEvent(QResizeEvent *event); + void wheelEvent(QWheelEvent *event); void keyPressEvent(QKeyEvent *event); + inline void mousePressEvent(QMouseEvent *event); + inline void mouseReleaseEvent(QMouseEvent *event); private: qreal scaleRatio_; + + public slots: + void fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRadioMode = Qt::KeepAspectRatio); + void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::KeepAspectRatio); + void fitInView(qreal x, qreal y, qreal w, qreal h, Qt::AspectRatioMode aspectRadioMode = Qt::KeepAspectRatio); }; +inline void GraphicsView::mouseReleaseEvent(QMouseEvent *event) +{ if(event->button() == Qt::RightButton) setCursor(QCursor(Qt::ArrowCursor)); QGraphicsView::mouseReleaseEvent(event); } + +void GraphicsView::mousePressEvent(QMouseEvent *event) +{ if(event->buttons() == Qt::RightButton) setCursor(QCursor(Qt::ClosedHandCursor)); QGraphicsView::mousePressEvent(event); } + #endif // GRAPHICSVIEW_H diff --git a/GScribo/Rendering/regionitem.h b/GScribo/Rendering/regionitem.h index 226d7ac..3e8eb11 100644 --- a/GScribo/Rendering/regionitem.h +++ b/GScribo/Rendering/regionitem.h @@ -72,9 +72,9 @@ inline void RegionItem::loadData(const GraphicsRegion::Data& data) { region_ = data.region; setColor(data.color); setZValue(data.zValue); } inline bool RegionItem::contains(const QPointF& point) -{ return (boundingRect().width() == 0 || boundingRect().height() == 0 || boundingRect().contains(point)) && shape().contains(point); } +{ return (boundingRect().width() * boundingRect().height() == 0 || boundingRect().contains(point)) && shape().contains(point); } inline bool RegionItem::intersects(const QRectF& rect) -{ return (boundingRect().width() == 0 || boundingRect().height() == 0 || boundingRect().intersects(rect)) && shape().intersects(rect); } +{ return (boundingRect().width() * boundingRect().height() == 0 || boundingRect().intersects(rect)) && shape().intersects(rect); } #endif // RegionITEM_H diff --git a/GScribo/Rendering/scene.cpp b/GScribo/Rendering/scene.cpp index e15d154..c7708d3 100644 --- a/GScribo/Rendering/scene.cpp +++ b/GScribo/Rendering/scene.cpp @@ -23,14 +23,24 @@ void Scene::init() isPressing_ = false; root_ = 0; - // Disable the scene size adaptation to items rect with a non null rect. - setSceneRect(0, 0, 0, 1); - - selection_.setRect(0, 0, 0, 0); + selection_.hide(); addItem(&selection_); } -void Scene::clear() +void Scene::clearAll() +{ + if(root_) + { + delete backgroundPixmap; + delete root_; + } + + selectedRegions_.clear(); + backgroundPixmap = 0; + root_ = 0; +} + +void Scene::clearRegions() { if(root_) delete root_; @@ -57,7 +67,7 @@ void Scene::clearSelection() void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if(event->button() == Qt::LeftButton && !isPressing_) + if(root_ && event->button() == Qt::LeftButton && !isPressing_) { isPressing_ = true; @@ -105,7 +115,7 @@ void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) emit newSelection(selectedRegions_); } - selection_.setRect(0, 0, 0, 1); + selection_.setRect(QRect()); selection_.hide(); } } @@ -213,7 +223,7 @@ void Scene::setVisible(const GraphicsRegion::Id& region, bool visible) void Scene::setRoot(RootGraphicsItem *root) { // Delete all items. - clear(); + clearRegions(); root_ = root; addItem(root); @@ -232,11 +242,14 @@ void Scene::changeScene(const QString& filename, RootGraphicsItem *root) backgroundPath_ = filename; // Delete all items. - clear(); + clearAll(); QPixmap pixmap(filename); setSceneRect(pixmap.rect()); - setBackgroundBrush(QBrush(pixmap)); + + // Create the background item and dock it at the maximal depth of the scene. + backgroundPixmap = new QGraphicsPixmapItem(pixmap, 0, this); + backgroundPixmap->setZValue(INT_MIN); // Add new items. if(root) diff --git a/GScribo/Rendering/scene.h b/GScribo/Rendering/scene.h index b51a36c..b658442 100644 --- a/GScribo/Rendering/scene.h +++ b/GScribo/Rendering/scene.h @@ -5,6 +5,7 @@ #include <QGraphicsView> #include <QGraphicsScene> #include <QFileDialog> +#include <climits> #include "rootgraphicsitem.h" #include "regionitem.h" @@ -41,9 +42,10 @@ class Scene : void select(QGraphicsItem *root, const QPointF& point, const QRectF& rect); QGraphicsView *mainView_; + RootGraphicsItem *root_; QString backgroundPath_; - RootGraphicsItem *root_; + QGraphicsPixmapItem *backgroundPixmap; Selection selection_; QList<RegionItem *> selectedRegions_; @@ -53,7 +55,8 @@ class Scene : bool isPressing_; public slots: - void clear(); + void clearAll(); + void clearRegions(); void clearSelection(); void select(const QList<RegionItem *>& selectedRegions); diff --git a/GScribo/Rendering/selection.cpp b/GScribo/Rendering/selection.cpp index dfe187e..f5c3f4a 100644 --- a/GScribo/Rendering/selection.cpp +++ b/GScribo/Rendering/selection.cpp @@ -30,7 +30,7 @@ void Selection::init() setPen(pen); QBrush brush; - brush.setStyle(Qt::Dense4Pattern); - brush.setColor(QColor::fromRgb(80, 200, 10, 100)); + brush.setStyle(Qt::SolidPattern); + brush.setColor(QColor::fromRgb(80, 200, 10, 60)); setBrush(brush); } diff --git a/GScribo/TODO b/GScribo/TODO index 8e5a474..b070107 100644 --- a/GScribo/TODO +++ b/GScribo/TODO @@ -3,6 +3,7 @@ Concerning the xml widget : - In the table tree (the attributes tree), set the max of the header splitter. Currently it can be moved indefinitely to the right. - Fit the splitter to the content of the first column when an attributes node is loaded. - My be some color corresponding to the graphics item of the scene. + - The organisation of the class and the two views are not perfect. Concerning the scene : @@ -11,16 +12,24 @@ Concerning the scene : - Optimize the collision between the rectangle item and the regions. Currently it do not take into account if the region is visible by the view before calculating the collision. - Use OpenGL to speed up graphics rendering (the gui has been developped with Qt 4.7, OpenGL was still experimental so it was really slow when updating the scene). - May be give the possibility to change the color. + - May be some options one right click. Concerning the region widget : - As stated bove, connect this widget with the xml widget. - - Find a better way to get region names and color. + - Find a better way to get region names and colors. -Concerning xml file : +Concerning the thumbnails widget : + - Load less thumbnails (just the necessary to draw it on the widget) because sometimes, pictures are heavy. + - May be use a progress dialog during the loading where a large number of pictures are loaded. + - Offer the possibility to down/ upscale thumbnails. + - Create also a button to delete selected items (rather than the key 'delete'). + + +Concerning the xml file : - Stop using the static array representation of the internal data structure for graphics region. - - find a better way to run through all node representing a graphics item without knowing it in advance. For exemple, the xml file looks like this : + - Find a better way to run through all node representing a graphics item without knowing it in advance. For exemple, the xml file looks like this : @@ -58,8 +67,21 @@ Concerning xml file : Graphical items are after pages and node containing informations looks like : *Region -> Coords -> Points and is located in the root node named "Page" so there is a way to find graphical item without knowing their location and name before. - Concerning tool bar : + - Create one \o/. - Create icons to replace text. - Add new functionnalities. + + +Create a text viewer : + - Give the possibility to modify the text. + - ______________________ move picture. + - ______________________ load arrays, tables, etc ... + - Create a custom tool bar to save, load, etc ... + + +For other idea of interfaces using Qt : + - gwenview (picture visionnary, good idea here). + + diff --git a/GScribo/XmlWidget/xmlwidget.h b/GScribo/XmlWidget/xmlwidget.h index 289b155..32eca37 100644 --- a/GScribo/XmlWidget/xmlwidget.h +++ b/GScribo/XmlWidget/xmlwidget.h @@ -42,13 +42,13 @@ class XmlWidget : inline void loadAttributes(const QModelIndex& index); }; -inline XmlView *XmlWidget::view() +inline XmlView * XmlWidget::view() { return &view_; } inline QTableView *XmlWidget::attributes() { return &attributes_; } -inline void XmlWidget::loadAttributes(const QModelIndex &index) +inline void XmlWidget::loadAttributes(const QModelIndex& index) { attributesModel_.load(index.data(Qt::UserRole+2).value<XmlItem *>()->attributes()); } #endif // XMLWIDGET_H diff --git a/GScribo/aboutdialog.h b/GScribo/aboutdialog.h new file mode 100644 index 0000000..31f6239 --- /dev/null +++ b/GScribo/aboutdialog.h @@ -0,0 +1,24 @@ +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include <QDialog> + +#include "ui_aboutdialog.h" + +namespace Ui +{ + class AboutDialog; +} + +class AboutDialog : + public QDialog +{ + public: + explicit AboutDialog() { ui = new Ui::AboutDialog; ui->setupUi(this); } + ~AboutDialog() { delete ui; } + + private: + Ui::AboutDialog *ui; +}; + +#endif // ABOUTDIALOG_H diff --git a/GScribo/aboutdialog.ui b/GScribo/aboutdialog.ui new file mode 100644 index 0000000..275e4ae --- /dev/null +++ b/GScribo/aboutdialog.ui @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AboutDialog</class> + <widget class="QDialog" name="AboutDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>557</width> + <height>390</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>557</width> + <height>390</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>557</width> + <height>390</height> + </size> + </property> + <property name="windowTitle"> + <string>About</string> + </property> + <property name="windowIcon"> + <iconset> + <normaloff>:/icons/shared/icons/olena_smaller.jpg</normaloff>:/icons/shared/icons/olena_smaller.jpg</iconset> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap>:/icons/shared/icons/olena_smaller.jpg</pixmap> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Document Image Analysis Tool</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; font-weight:600;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This project is powered by <span style=" font-weight:600; font-style:italic;">Milena</span>, a generic image processing library.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is part of <span style=" font-weight:600; font-style:italic;">Olena</span>, an Image Processing Platform and its module <span style=" font-weight:600; font-style:italic;">Scribo</span>, a set of tools for Document Image Analysis.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://olena.lrde.epita.fr"><span style=" text-decoration: underline; color:#0057ae;">http://olena.lrde.epita.fr</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Thanks to Arthur Crépin-Leblond, Samuel Da Mota, Loic Denuziere, </span><span style=" font-size:8pt;">Jérôme Galtier,</span><span style=" font-size:8pt;"> </span><span style=" font-size:8pt;">Florent d'Halluin, </span><span style=" font-size:8pt;">Alex Hamelin, </span><span style=" font-size:8pt;">Damien Lefortier, </span><span style=" font-size:8pt;">Vincent Ordy, </span><span style=" font-size:8pt;">Guillaume Sadegh and</span><span style=" font-size:8pt;"> </span><span style=" font-size:8pt;">Warren Seine </span><span style=" font-size:8pt;">for their contribution.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt;">This application has been developed in the context of the SCRIBO project of the Free Software Thematic Group, part of the "System@tic Paris-Région" Cluster (France). This project is partially funded by the French Government, its economic development agencies, and by the Paris-Région institutions.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:7pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt;">Copyright (C) 2010, 2011 EPITA Research and Development Laboratory (LRDE)</span></p></body></html></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Ok</set> + </property> + <property name="centerButtons"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>AboutDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>281</x> + <y>391</y> + </hint> + <hint type="destinationlabel"> + <x>240</x> + <y>203</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/GScribo/dockwidget.h b/GScribo/dockwidget.h new file mode 100644 index 0000000..a1a2b40 --- /dev/null +++ b/GScribo/dockwidget.h @@ -0,0 +1,22 @@ +#ifndef DOCKWIDGET_H +#define DOCKWIDGET_H + +#include <QDockWidget> + +class DockWidget : + public QDockWidget +{ + Q_OBJECT + + public: + explicit DockWidget(QWidget *parent = 0, Qt::WindowFlags flags = 0) : QDockWidget(parent, flags) { } + explicit DockWidget(const QString& title, QWidget *parent = 0, Qt::WindowFlags flags = 0) : QDockWidget(title, parent, flags) { } + + public slots: + inline void switchVisibility(); +}; + +inline void DockWidget::switchVisibility() +{ setVisible(!isVisible()); } + +#endif // DOCKWIDGET_H diff --git a/GScribo/graphicswidget.h b/GScribo/graphicswidget.h new file mode 100644 index 0000000..ffb9aff --- /dev/null +++ b/GScribo/graphicswidget.h @@ -0,0 +1,18 @@ +#ifndef GRAPHICSWIDGET_H +#define GRAPHICSWIDGET_H + +#include <QWidget> + + +class GraphicsWidget : + public QWidget +{ + public: + explicit GraphicsWidget(QWidget *parent, Qt::WindowFlags f); + + private: + + +}; + +#endif // GRAPHICSWIDGET_H diff --git a/GScribo/helpdialog.cpp b/GScribo/helpdialog.cpp new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/GScribo/helpdialog.cpp @@ -0,0 +1 @@ + diff --git a/GScribo/mainwindow.cpp b/GScribo/mainwindow.cpp index bcb52d2..e3d7096 100644 --- a/GScribo/mainwindow.cpp +++ b/GScribo/mainwindow.cpp @@ -8,6 +8,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->setupUi(this); setWindowTitle(tr("GScribo")); + statusBar()->hide(); initGraphicsRegion(); initTextRegion(); @@ -56,6 +57,7 @@ void MainWindow::initPageWidget() dockPages_.setWindowTitle("Pages"); dockPages_.setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); dockPages_.setWidget(&pagesWidget_); + dockPages_.setMinimumWidth(190); addDockWidget(Qt::LeftDockWidgetArea, &dockPages_); } @@ -76,6 +78,7 @@ void MainWindow::initXmlWidget() dockXml_.setWidget(&xmlWidget_); addDockWidget(Qt::BottomDockWidgetArea, &dockXml_); + dockXml_.setVisible(false); } void MainWindow::initTextRegion() @@ -99,12 +102,43 @@ void MainWindow::initToolBar() void MainWindow::initMenuBar() { + QMenu *menuFile = ui->menuBar->addMenu(tr("File")); + + QAction *open = menuFile->addAction(tr("Open")); + connect(open, SIGNAL(triggered()), SLOT(onOpen())); + + QAction *segment = menuFile->addAction(tr("Segment")); + connect(segment, SIGNAL(triggered()), this, SLOT(onSegment())); + + QMenu *menuAreas = ui->menuBar->addMenu(tr("Areas")); + + QAction *page = menuAreas->addAction(tr("Page")); + page->setCheckable(true); + page->setChecked(true); + connect(page, SIGNAL(triggered()), &dockPages_, SLOT(switchVisibility())); + + QAction *region = menuAreas->addAction(tr("Region")); + region->setCheckable(true); + region->setChecked(true); + connect(region, SIGNAL(triggered()), &dockRegion_, SLOT(switchVisibility())); + + QAction *xml = menuAreas->addAction(tr("Xml")); + xml->setCheckable(true); + xml->setChecked(false); + connect(xml, SIGNAL(triggered()), &dockXml_, SLOT(switchVisibility())); + QAction *preferences = ui->menuBar->addAction(tr("Preferences")); connect(preferences, SIGNAL(triggered()), SLOT(onPreferences())); + + QAction *about = ui->menuBar->addAction(tr("About")); + connect(about, SIGNAL(triggered()), SLOT(onAbout())); } void MainWindow::connectWidgets() { + // Each time the scene rect change (when a new picture is loaded), we fit the scene background rectangle in the view. + connect(&scene_, SIGNAL(sceneRectChanged(QRectF)), &graphicsView_, SLOT(fitInView(QRectF))); + // If double click on a picture of the page widget -> draw it on background scene. connect(&pagesWidget_, SIGNAL(imageSelectionned(QString)), this, SLOT(onFileChanged(QString))); @@ -117,6 +151,7 @@ void MainWindow::connectWidgets() // Connect the scene with the region widget. connect(®ionWidget_, SIGNAL(checkStateChanged(GraphicsRegion::Id,bool)), &scene_, SLOT(setVisible(GraphicsRegion::Id,bool))); + // Connect the xml widget with the region widget. connect(®ionWidget_, SIGNAL(checkStateChanged(QString)), xmlWidget_.view(), SLOT(setFilterString(QString))); @@ -193,6 +228,12 @@ void MainWindow::onPreferences() preferenceDialog->show(); } +void MainWindow::onAbout() +{ + AboutDialog *about = new AboutDialog; + about->show(); +} + void MainWindow::onXmlSaved(const QString& filename) { xml_.load(filename); diff --git a/GScribo/mainwindow.h b/GScribo/mainwindow.h index c6cd1d7..9569a70 100644 --- a/GScribo/mainwindow.h +++ b/GScribo/mainwindow.h @@ -17,6 +17,8 @@ //#include "Processing/runner.h" #include "Rendering/scene.h" #include "regionwidget.h" +#include "aboutdialog.h" +#include "dockwidget.h" #include "xml.h" namespace Ui @@ -52,12 +54,12 @@ class MainWindow: Ui::MainWindow *ui; - QDockWidget dockRegion_; - QDockWidget dockPages_; - QDockWidget dockText_; - QDockWidget dockXml_; + DockWidget dockRegion_; + DockWidget dockPages_; + DockWidget dockText_; + DockWidget dockXml_; - QGraphicsView graphicsView_; + GraphicsView graphicsView_; Scene scene_; PagesWidget pagesWidget_; @@ -75,6 +77,7 @@ class MainWindow: void onOpen(); void onSegment(); void onPreferences(); + void onAbout(); void onXmlSaved(const QString& filename); void onFileChanged(const QString& filename); diff --git a/Test2/l.txt b/Test2/l.txt new file mode 100644 index 0000000..8ef2318 --- /dev/null +++ b/Test2/l.txt @@ -0,0 +1 @@ +(entrée standard) -- 1.7.2.5