mirror of https://github.com/KLayout/klayout.git
commit
f7173d0da4
|
|
@ -143,6 +143,22 @@ Manager::last_transaction_id () const
|
|||
return m_transactions.empty () ? 0 : reinterpret_cast<transaction_id_t> (& m_transactions.back ());
|
||||
}
|
||||
|
||||
void
|
||||
Manager::cancel ()
|
||||
{
|
||||
if (db::transactions_enabled ()) {
|
||||
|
||||
// commit and undo - revert changes done so far
|
||||
commit ();
|
||||
undo ();
|
||||
|
||||
// delete all following transactions
|
||||
erase_transactions (m_current, m_transactions.end ());
|
||||
m_current = m_transactions.end ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Manager::commit ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -140,6 +140,14 @@ public:
|
|||
*/
|
||||
void commit ();
|
||||
|
||||
/**
|
||||
* @brief Cancels a transaction
|
||||
*
|
||||
* If called instead of commit, this method will undo all operations of the pending
|
||||
* transaction.
|
||||
*/
|
||||
void cancel ();
|
||||
|
||||
/**
|
||||
* @brief Undo the current transaction
|
||||
*
|
||||
|
|
@ -256,13 +264,20 @@ private:
|
|||
*
|
||||
* This object controls a transaction through it's lifetime. On construction, the
|
||||
* transaction is started, on destruction, the transaction is committed.
|
||||
*
|
||||
* "cancel" can be used to cancel the operation. This will undo all operations collected
|
||||
* so far and delete the transaction.
|
||||
*
|
||||
* "close" temporarily disable the collection of operations.
|
||||
* "open" will enable operation collection again and continue
|
||||
* collection at the point when it was stopped with "close".
|
||||
*/
|
||||
|
||||
class DB_PUBLIC Transaction
|
||||
{
|
||||
public:
|
||||
Transaction (db::Manager *manager, const std::string &desc)
|
||||
: mp_manager (manager), m_transaction_id (0)
|
||||
: mp_manager (manager), m_transaction_id (0), m_description (desc)
|
||||
{
|
||||
if (mp_manager) {
|
||||
m_transaction_id = mp_manager->transaction (desc);
|
||||
|
|
@ -270,7 +285,7 @@ public:
|
|||
}
|
||||
|
||||
Transaction (db::Manager *manager, const std::string &desc, db::Manager::transaction_id_t join_with)
|
||||
: mp_manager (manager), m_transaction_id (0)
|
||||
: mp_manager (manager), m_transaction_id (0), m_description (desc)
|
||||
{
|
||||
if (mp_manager) {
|
||||
m_transaction_id = mp_manager->transaction (desc, join_with);
|
||||
|
|
@ -280,11 +295,36 @@ public:
|
|||
~Transaction ()
|
||||
{
|
||||
if (mp_manager) {
|
||||
mp_manager->commit ();
|
||||
if (mp_manager->transacting ()) {
|
||||
mp_manager->commit ();
|
||||
}
|
||||
mp_manager = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void cancel ()
|
||||
{
|
||||
if (mp_manager) {
|
||||
open ();
|
||||
mp_manager->cancel ();
|
||||
mp_manager = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void close ()
|
||||
{
|
||||
if (mp_manager->transacting ()) {
|
||||
mp_manager->commit ();
|
||||
}
|
||||
}
|
||||
|
||||
void open ()
|
||||
{
|
||||
if (! mp_manager->transacting ()) {
|
||||
mp_manager->transaction (m_description, m_transaction_id);
|
||||
}
|
||||
}
|
||||
|
||||
db::Manager::transaction_id_t id () const
|
||||
{
|
||||
return m_transaction_id;
|
||||
|
|
@ -293,6 +333,7 @@ public:
|
|||
private:
|
||||
db::Manager *mp_manager;
|
||||
db::Manager::transaction_id_t m_transaction_id;
|
||||
std::string m_description;
|
||||
|
||||
// no copying.
|
||||
Transaction (const Transaction &);
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@ struct B : public db::Object
|
|||
{
|
||||
if (transacting ()) {
|
||||
manager ()->queue (this, new BO (d));
|
||||
} else {
|
||||
x += d;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,3 +232,84 @@ TEST(2)
|
|||
EXPECT_EQ (BO::inst_count (), 0);
|
||||
}
|
||||
|
||||
TEST(3)
|
||||
{
|
||||
db::Manager *man = new db::Manager ();
|
||||
{
|
||||
EXPECT_EQ (man->available_undo ().first, false);
|
||||
EXPECT_EQ (man->available_redo ().first, false);
|
||||
|
||||
B b (man);
|
||||
man->transaction ("add 1");
|
||||
b.add (1);
|
||||
man->commit ();
|
||||
|
||||
EXPECT_EQ (b.x, 1);
|
||||
EXPECT_EQ (man->available_undo ().first, true);
|
||||
EXPECT_EQ (man->available_undo ().second, "add 1");
|
||||
|
||||
man->transaction ("add 1,2");
|
||||
b.add (1);
|
||||
b.add (2);
|
||||
man->cancel ();
|
||||
EXPECT_EQ (b.x, 1);
|
||||
EXPECT_EQ (man->available_undo ().first, true);
|
||||
EXPECT_EQ (man->available_redo ().first, false);
|
||||
|
||||
man->undo ();
|
||||
EXPECT_EQ (b.x, 0);
|
||||
EXPECT_EQ (man->available_undo ().first, false);
|
||||
EXPECT_EQ (man->available_redo ().first, true);
|
||||
}
|
||||
|
||||
delete man;
|
||||
EXPECT_EQ (BO::inst_count (), 0);
|
||||
}
|
||||
|
||||
TEST(4)
|
||||
{
|
||||
db::Manager *man = new db::Manager ();
|
||||
{
|
||||
EXPECT_EQ (man->available_undo ().first, false);
|
||||
EXPECT_EQ (man->available_redo ().first, false);
|
||||
|
||||
B b (man);
|
||||
{
|
||||
db::Transaction t (man, "add 1");
|
||||
b.add (1);
|
||||
}
|
||||
|
||||
EXPECT_EQ (b.x, 1);
|
||||
EXPECT_EQ (man->available_undo ().first, true);
|
||||
EXPECT_EQ (man->available_undo ().second, "add 1");
|
||||
|
||||
{
|
||||
db::Transaction t (man, "add 1,2");
|
||||
b.add (1);
|
||||
EXPECT_EQ (b.x, 2);
|
||||
EXPECT_EQ (man->transacting (), true);
|
||||
t.close ();
|
||||
EXPECT_EQ (man->transacting (), false);
|
||||
b.add (1); // after close -> not undone!
|
||||
EXPECT_EQ (b.x, 3);
|
||||
t.open ();
|
||||
EXPECT_EQ (man->transacting (), true);
|
||||
b.add (2);
|
||||
EXPECT_EQ (b.x, 5);
|
||||
t.cancel ();
|
||||
}
|
||||
|
||||
EXPECT_EQ (b.x, 2);
|
||||
EXPECT_EQ (man->available_undo ().first, true);
|
||||
EXPECT_EQ (man->available_redo ().first, false);
|
||||
|
||||
man->undo ();
|
||||
EXPECT_EQ (b.x, 1);
|
||||
EXPECT_EQ (man->available_undo ().first, false);
|
||||
EXPECT_EQ (man->available_redo ().first, true);
|
||||
}
|
||||
|
||||
delete man;
|
||||
EXPECT_EQ (BO::inst_count (), 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -434,9 +434,10 @@ CustomizeMenuConfigPage::apply (const std::vector<std::pair<std::string, std::st
|
|||
// extract the top level menues
|
||||
std::map <std::string, std::string> top_level_menus;
|
||||
top_level_menus.insert (std::make_pair (std::string (), tl::to_string (QObject::tr ("Main Menu"))));
|
||||
top_level_menus.insert (std::make_pair (std::string ("secrets"), tl::to_string (QObject::tr ("Key Binding Targets"))));
|
||||
top_level_menus.insert (std::make_pair (std::string ("lcp_context_menu"), tl::to_string (QObject::tr ("Layer Panel Context Menu"))));
|
||||
top_level_menus.insert (std::make_pair (std::string ("hcp_context_menu"), tl::to_string (QObject::tr ("Cell List Context Menu"))));
|
||||
|
||||
|
||||
// fill the bindings list
|
||||
mp_ui->bindings_list->clear ();
|
||||
|
||||
|
|
|
|||
|
|
@ -742,6 +742,13 @@ MainWindow::init_menu ()
|
|||
{
|
||||
// default menu layout
|
||||
|
||||
MenuLayoutEntry secret_menu [] = {
|
||||
MenuLayoutEntry ("paste_interactive:edit", tl::to_string (QObject::tr ("Paste Interactive")), SLOT (cm_paste_interactive ())),
|
||||
MenuLayoutEntry ("duplicate_interactive:edit", tl::to_string (QObject::tr ("Duplicate Interactive")), SLOT (cm_duplicate_interactive ())),
|
||||
MenuLayoutEntry ("sel_move_interactive", tl::to_string (QObject::tr ("Move Interactive")), SLOT (cm_sel_move_interactive ())),
|
||||
MenuLayoutEntry::last ()
|
||||
};
|
||||
|
||||
MenuLayoutEntry empty_menu [] = {
|
||||
MenuLayoutEntry::last ()
|
||||
};
|
||||
|
|
@ -995,6 +1002,7 @@ MainWindow::init_menu ()
|
|||
MenuLayoutEntry ("macros_menu", tl::to_string (QObject::tr ("&Macros")), macros_menu),
|
||||
MenuLayoutEntry::separator ("help_group"),
|
||||
MenuLayoutEntry ("help_menu", tl::to_string (QObject::tr ("&Help")), help_menu),
|
||||
MenuLayoutEntry ("@secrets", tl::to_string (QObject::tr ("Secret Features")), secret_menu),
|
||||
MenuLayoutEntry ("@toolbar", "", toolbar_entries),
|
||||
MenuLayoutEntry::last ()
|
||||
};
|
||||
|
|
@ -2233,7 +2241,7 @@ MainWindow::cm_cell_copy ()
|
|||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_duplicate ()
|
||||
MainWindow::do_cm_duplicate (bool interactive)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
|
|
@ -2248,7 +2256,11 @@ MainWindow::cm_duplicate ()
|
|||
current_view ()->copy ();
|
||||
current_view ()->clear_selection ();
|
||||
current_view ()->cancel ();
|
||||
current_view ()->paste ();
|
||||
if (interactive) {
|
||||
current_view ()->paste_interactive ();
|
||||
} else {
|
||||
current_view ()->paste ();
|
||||
}
|
||||
db::Clipboard::instance ().swap (saved_clipboard);
|
||||
} catch (...) {
|
||||
db::Clipboard::instance ().swap (saved_clipboard);
|
||||
|
|
@ -2260,6 +2272,26 @@ MainWindow::cm_duplicate ()
|
|||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_duplicate ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
do_cm_duplicate (false);
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_duplicate_interactive ()
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
do_cm_duplicate (true);
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_copy ()
|
||||
{
|
||||
|
|
@ -2274,19 +2306,35 @@ MainWindow::cm_copy ()
|
|||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_paste ()
|
||||
MainWindow::do_cm_paste (bool interactive)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
|
||||
if (current_view () && ! db::Clipboard::instance ().empty ()) {
|
||||
current_view ()->cancel ();
|
||||
current_view ()->clear_selection ();
|
||||
current_view ()->paste ();
|
||||
if (interactive) {
|
||||
current_view ()->paste_interactive ();
|
||||
} else {
|
||||
current_view ()->paste ();
|
||||
}
|
||||
}
|
||||
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_paste ()
|
||||
{
|
||||
do_cm_paste (false);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_paste_interactive ()
|
||||
{
|
||||
do_cm_paste (true);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_cut ()
|
||||
{
|
||||
|
|
@ -3568,6 +3616,12 @@ MainWindow::cm_sel_move_to ()
|
|||
call_on_current_view (&lay::LayoutView::cm_sel_move_to, tl::to_string (QObject::tr ("move selection to position")));
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_sel_move_interactive ()
|
||||
{
|
||||
call_on_current_view (&lay::LayoutView::cm_sel_move_interactive, tl::to_string (QObject::tr ("move selection interactively")));
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::cm_sel_scale ()
|
||||
{
|
||||
|
|
@ -3685,19 +3739,7 @@ MainWindow::clone_current_view ()
|
|||
|
||||
// create a new view
|
||||
view = new lay::LayoutView (current_view (), &m_manager, lay::ApplicationBase::instance ()->is_editable (), plugin_root (), mp_view_stack);
|
||||
connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ()));
|
||||
connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ()));
|
||||
connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ()));
|
||||
connect (view, SIGNAL (menu_needs_update ()), this, SLOT (menu_needs_update ()));
|
||||
connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int)));
|
||||
connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool)));
|
||||
connect (view, SIGNAL (clear_current_pos ()), this, SLOT (clear_current_pos ()));
|
||||
mp_views.push_back (view);
|
||||
|
||||
// we must resize the widget here to set the geometry properly.
|
||||
// This is required to make zoom_fit work.
|
||||
view->setGeometry (0, 0, mp_view_stack->width (), mp_view_stack->height ());
|
||||
view->show ();
|
||||
add_view (view);
|
||||
|
||||
// set initial attributes
|
||||
view->set_hier_levels (curr->get_hier_levels ());
|
||||
|
|
@ -4291,12 +4333,9 @@ MainWindow::create_layout (const std::string &technology, int mode)
|
|||
return create_or_load_layout (0, 0, technology, mode);
|
||||
}
|
||||
|
||||
int
|
||||
MainWindow::do_create_view ()
|
||||
void
|
||||
MainWindow::add_view (lay::LayoutView *view)
|
||||
{
|
||||
// create a new view
|
||||
lay::LayoutView *view = new lay::LayoutView (&m_manager, lay::ApplicationBase::instance ()->is_editable (), plugin_root (), mp_view_stack);
|
||||
|
||||
connect (view, SIGNAL (title_changed ()), this, SLOT (view_title_changed ()));
|
||||
connect (view, SIGNAL (dirty_changed ()), this, SLOT (view_title_changed ()));
|
||||
connect (view, SIGNAL (edits_enabled_changed ()), this, SLOT (edits_enabled_changed ()));
|
||||
|
|
@ -4304,6 +4343,7 @@ MainWindow::do_create_view ()
|
|||
connect (view, SIGNAL (show_message (const std::string &, int)), this, SLOT (message (const std::string &, int)));
|
||||
connect (view, SIGNAL (current_pos_changed (double, double, bool)), this, SLOT (current_pos (double, double, bool)));
|
||||
connect (view, SIGNAL (clear_current_pos ()), this, SLOT (clear_current_pos ()));
|
||||
connect (view, SIGNAL (mode_change (int)), this, SLOT (select_mode (int)));
|
||||
|
||||
mp_views.push_back (view);
|
||||
|
||||
|
|
@ -4311,6 +4351,14 @@ MainWindow::do_create_view ()
|
|||
// This is required to make zoom_fit work.
|
||||
view->setGeometry (0, 0, mp_view_stack->width (), mp_view_stack->height ());
|
||||
view->show ();
|
||||
}
|
||||
|
||||
int
|
||||
MainWindow::do_create_view ()
|
||||
{
|
||||
// create a new view
|
||||
lay::LayoutView *view = new lay::LayoutView (&m_manager, lay::ApplicationBase::instance ()->is_editable (), plugin_root (), mp_view_stack);
|
||||
add_view (view);
|
||||
|
||||
// set initial attributes
|
||||
view->set_synchronous (synchronous ());
|
||||
|
|
|
|||
|
|
@ -504,13 +504,6 @@ public:
|
|||
*/
|
||||
void select_view (int index);
|
||||
|
||||
/**
|
||||
* @brief Select the given mode
|
||||
*
|
||||
* @param The index of the mode to select
|
||||
*/
|
||||
void select_mode (int m);
|
||||
|
||||
/**
|
||||
* @brief Get the instance of the assistant
|
||||
*/
|
||||
|
|
@ -645,17 +638,17 @@ signals:
|
|||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Display the current position
|
||||
* @brief Displays the current position
|
||||
*/
|
||||
void current_pos (double x, double y, bool dbu_units);
|
||||
|
||||
/**
|
||||
* @brief Clear the current position
|
||||
* @brief Clears the current position
|
||||
*/
|
||||
void clear_current_pos ();
|
||||
|
||||
/**
|
||||
* @brief Display a status message next to the coordinates
|
||||
* @brief Displays a status message next to the coordinates
|
||||
*/
|
||||
void message (const std::string &s, int ms);
|
||||
|
||||
|
|
@ -664,6 +657,13 @@ public slots:
|
|||
*/
|
||||
void clear_message ();
|
||||
|
||||
/**
|
||||
* @brief Selects the given mode
|
||||
*
|
||||
* @param The index of the mode to select
|
||||
*/
|
||||
void select_mode (int m);
|
||||
|
||||
/**
|
||||
* @brief Called when one of the built-in modes (i.e. select, move) is selected
|
||||
*/
|
||||
|
|
@ -691,7 +691,9 @@ public slots:
|
|||
void cm_show_properties ();
|
||||
void cm_copy ();
|
||||
void cm_paste ();
|
||||
void cm_paste_interactive ();
|
||||
void cm_duplicate ();
|
||||
void cm_duplicate_interactive ();
|
||||
void cm_cut ();
|
||||
void cm_zoom_fit_sel ();
|
||||
void cm_zoom_fit ();
|
||||
|
|
@ -772,6 +774,7 @@ public slots:
|
|||
void cm_sel_scale ();
|
||||
void cm_sel_move ();
|
||||
void cm_sel_move_to ();
|
||||
void cm_sel_move_interactive ();
|
||||
void cm_show_assistant ();
|
||||
|
||||
// forwarded to the current view: layer list context menu
|
||||
|
|
@ -946,6 +949,9 @@ private:
|
|||
void closeEvent (QCloseEvent *event);
|
||||
void resizeEvent (QResizeEvent *event);
|
||||
|
||||
void do_cm_paste (bool interactive);
|
||||
void do_cm_duplicate (bool interactive);
|
||||
|
||||
void format_message ();
|
||||
|
||||
int dirty_files (std::string &dirty_files);
|
||||
|
|
@ -956,6 +962,7 @@ private:
|
|||
void current_view_changed ();
|
||||
void update_window_title ();
|
||||
void update_tab_title (int i);
|
||||
void add_view (LayoutView *view);
|
||||
|
||||
bool can_close ();
|
||||
lay::CellViewRef create_or_load_layout (const std::string *filename, const db::LoadLayoutOptions *options, const std::string &tech, const int mode);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "layPropertiesDialog.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
|
@ -82,25 +83,30 @@ Editables::~Editables ()
|
|||
}
|
||||
|
||||
void
|
||||
Editables::del ()
|
||||
Editables::del (db::Transaction *transaction)
|
||||
{
|
||||
std::auto_ptr<db::Transaction> trans_holder (transaction ? transaction : new db::Transaction (manager (), tl::to_string (QObject::tr ("Delete"))));
|
||||
|
||||
if (selection_size () > 0) {
|
||||
|
||||
cancel_edits ();
|
||||
try {
|
||||
|
||||
// begin the transaction
|
||||
tl_assert (! manager ()->transacting ());
|
||||
manager ()->transaction (tl::to_string (QObject::tr ("Delete")));
|
||||
// this dummy operation will update the screen:
|
||||
manager ()->queue (this, new db::Op ());
|
||||
trans_holder->open ();
|
||||
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
e->del ();
|
||||
cancel_edits ();
|
||||
|
||||
// this dummy operation will update the screen:
|
||||
manager ()->queue (this, new db::Op ());
|
||||
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
e->del ();
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
trans_holder->cancel ();
|
||||
throw;
|
||||
}
|
||||
|
||||
// end the transaction
|
||||
manager ()->commit ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,14 +161,16 @@ Editables::selection_catch_bbox ()
|
|||
}
|
||||
|
||||
void
|
||||
Editables::transform (const db::DCplxTrans &tr)
|
||||
Editables::transform (const db::DCplxTrans &tr, db::Transaction *transaction)
|
||||
{
|
||||
std::auto_ptr<db::Transaction> trans_holder (transaction ? transaction : new db::Transaction (manager (), tl::to_string (QObject::tr ("Transform"))));
|
||||
|
||||
if (selection_size () > 0) {
|
||||
|
||||
try {
|
||||
|
||||
tl_assert (! manager ()->transacting ());
|
||||
manager ()->transaction (tl::to_string (QObject::tr ("Transform")));
|
||||
trans_holder->open ();
|
||||
|
||||
// this dummy operation will update the screen:
|
||||
manager ()->queue (this, new db::Op ());
|
||||
|
||||
|
|
@ -170,11 +178,8 @@ Editables::transform (const db::DCplxTrans &tr)
|
|||
e->transform (tr);
|
||||
}
|
||||
|
||||
// end the transaction
|
||||
manager ()->commit ();
|
||||
|
||||
} catch (...) {
|
||||
manager ()->clear ();
|
||||
trans_holder->cancel ();
|
||||
throw;
|
||||
}
|
||||
|
||||
|
|
@ -525,13 +530,14 @@ Editables::move_transform (const db::DPoint &p, db::DFTrans t, lay::angle_constr
|
|||
}
|
||||
|
||||
void
|
||||
Editables::end_move (const db::DPoint &p, lay::angle_constraint_type ac)
|
||||
Editables::end_move (const db::DPoint &p, lay::angle_constraint_type ac, db::Transaction *transaction)
|
||||
{
|
||||
std::auto_ptr<db::Transaction> trans_holder (transaction ? transaction : new db::Transaction (manager (), tl::to_string (QObject::tr ("Move"))));
|
||||
|
||||
if (m_any_move_operation) {
|
||||
|
||||
// begin the transaction
|
||||
tl_assert (! manager ()->transacting ());
|
||||
manager ()->transaction (tl::to_string (QObject::tr ("Move")));
|
||||
trans_holder->open ();
|
||||
|
||||
// this dummy operation will update the screen:
|
||||
manager ()->queue (this, new db::Op ());
|
||||
|
||||
|
|
@ -539,9 +545,6 @@ Editables::end_move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
e->end_move (p, ac);
|
||||
}
|
||||
|
||||
// end the transaction
|
||||
manager ()->commit ();
|
||||
|
||||
// clear the selection that was set previously
|
||||
if (m_move_selection) {
|
||||
clear_selection ();
|
||||
|
|
@ -549,6 +552,8 @@ Editables::end_move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
|
||||
} else {
|
||||
|
||||
trans_holder->cancel ();
|
||||
|
||||
// if nothing was moved, treat the end_move as a select which makes the move sticky or
|
||||
// replaces a complex selection by a simple one
|
||||
edit_cancel ();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "dbPoint.h"
|
||||
#include "dbBox.h"
|
||||
#include "dbObject.h"
|
||||
#include "dbManager.h"
|
||||
|
||||
#include <set>
|
||||
#include <limits>
|
||||
|
|
@ -386,8 +387,11 @@ public:
|
|||
|
||||
/**
|
||||
* @brief The delete operation
|
||||
*
|
||||
* If a transaction is given, the operation will be appended to this pending transaction
|
||||
* The Editables object takes ownership over the Transaction object.
|
||||
*/
|
||||
void del ();
|
||||
void del (db::Transaction *transaction = 0);
|
||||
|
||||
/**
|
||||
* @brief "cut" operation
|
||||
|
|
@ -419,8 +423,11 @@ public:
|
|||
* @brief transform the selection
|
||||
*
|
||||
* The transformation is given in micron units.
|
||||
*
|
||||
* If a transaction is given, the operation will be appended to this pending transaction.
|
||||
* The Editables object takes ownership over the Transaction object.
|
||||
*/
|
||||
void transform (const db::DCplxTrans &tr);
|
||||
void transform (const db::DCplxTrans &tr, db::Transaction *transaction = 0);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable a certain editable
|
||||
|
|
@ -494,8 +501,11 @@ public:
|
|||
|
||||
/**
|
||||
* @brief End "move" operation
|
||||
*
|
||||
* If a transaction is given, the operation will be appended to this pending transaction
|
||||
* The Editables object takes ownership over the Transaction object.
|
||||
*/
|
||||
void end_move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
void end_move (const db::DPoint &p, lay::angle_constraint_type ac, db::Transaction *transaction = 0);
|
||||
|
||||
/**
|
||||
* @brief Tell how many objects are selected.
|
||||
|
|
|
|||
|
|
@ -5085,6 +5085,33 @@ LayoutView::paste ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutView::paste_interactive ()
|
||||
{
|
||||
clear_selection ();
|
||||
|
||||
std::auto_ptr<db::Transaction> trans (new db::Transaction (manager (), tl::to_string (QObject::tr ("Paste and move"))));
|
||||
|
||||
{
|
||||
// let the receivers sort out who is pasting what ..
|
||||
if (mp_hierarchy_panel) {
|
||||
mp_hierarchy_panel->paste ();
|
||||
}
|
||||
if (mp_control_panel) {
|
||||
mp_control_panel->paste ();
|
||||
}
|
||||
lay::Editables::paste ();
|
||||
}
|
||||
|
||||
// temporarily close the transaction and pass to the move service for appending it's own
|
||||
// operations.
|
||||
trans->close ();
|
||||
|
||||
if (mp_move_service->begin_move (trans.release ())) {
|
||||
switch_mode (-1); // move mode
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutView::copy ()
|
||||
{
|
||||
|
|
@ -6763,6 +6790,23 @@ LayoutView::cm_sel_scale ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutView::cm_sel_move_interactive ()
|
||||
{
|
||||
if (mp_move_service->begin_move ()) {
|
||||
switch_mode (-1); // move mode
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutView::switch_mode (int m)
|
||||
{
|
||||
if (m_mode != m) {
|
||||
mode (m);
|
||||
emit mode_change (m);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayoutView::cm_sel_move_to ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -254,6 +254,11 @@ public:
|
|||
*/
|
||||
void paste ();
|
||||
|
||||
/**
|
||||
* @brief Pastes from clipboard and initiates a move
|
||||
*/
|
||||
void paste_interactive ();
|
||||
|
||||
/**
|
||||
* @brief Copies to clipboard
|
||||
*
|
||||
|
|
@ -1617,6 +1622,14 @@ public:
|
|||
*/
|
||||
void mode (int m);
|
||||
|
||||
/**
|
||||
* @brief Switches the application's mode
|
||||
*
|
||||
* Switches the mode on application level. Use this method to initiate
|
||||
* a mode switch from the view.
|
||||
*/
|
||||
void switch_mode (int m);
|
||||
|
||||
/**
|
||||
* @brief Test, if the view is currently in move mode.
|
||||
*/
|
||||
|
|
@ -2582,6 +2595,7 @@ public slots:
|
|||
void cm_sel_scale ();
|
||||
void cm_sel_move ();
|
||||
void cm_sel_move_to ();
|
||||
void cm_sel_move_interactive ();
|
||||
|
||||
// forwarded to the layer control panel
|
||||
void cm_new_tab ();
|
||||
|
|
@ -2698,6 +2712,11 @@ signals:
|
|||
*/
|
||||
void menu_needs_update ();
|
||||
|
||||
/**
|
||||
* @brief The view initiated a mode change
|
||||
*/
|
||||
void mode_change (int m);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Establish the view operations
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ MoveService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool
|
|||
return true;
|
||||
}
|
||||
if (prio && (buttons & lay::LeftButton) != 0) {
|
||||
if (handle_dragging (p, buttons)) {
|
||||
if (handle_dragging (p, buttons, 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -216,7 +216,7 @@ bool
|
|||
MoveService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
if (prio && (buttons & lay::LeftButton) != 0) {
|
||||
if (handle_dragging (p, buttons)) {
|
||||
if (handle_dragging (p, buttons, 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -229,12 +229,34 @@ MoveService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MoveService::begin_move (db::Transaction *transaction)
|
||||
{
|
||||
std::auto_ptr<db::Transaction> trans_holder (transaction);
|
||||
|
||||
drag_cancel ();
|
||||
|
||||
db::DBox bbox = mp_editables->selection_bbox ();
|
||||
if (bbox.empty ()) {
|
||||
// nothing selected
|
||||
return false;
|
||||
}
|
||||
|
||||
set_cursor (lay::Cursor::size_all);
|
||||
|
||||
// emulate a "begin move" at the center of the selection bbox - this will become the reference point
|
||||
return handle_dragging (bbox.center (), 0, trans_holder.release ());
|
||||
}
|
||||
|
||||
bool
|
||||
MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons)
|
||||
MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons, db::Transaction *transaction)
|
||||
{
|
||||
std::auto_ptr<db::Transaction> trans_holder (transaction);
|
||||
|
||||
if (! m_dragging) {
|
||||
|
||||
mp_transaction.reset (trans_holder.release ());
|
||||
|
||||
if (mp_editables->begin_move (p, ac_from_buttons (buttons))) {
|
||||
|
||||
lay::SelectionService *selector = mp_view->selection_service ();
|
||||
|
|
@ -257,7 +279,7 @@ MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons)
|
|||
|
||||
m_dragging = false;
|
||||
widget ()->ungrab_mouse (this);
|
||||
mp_editables->end_move (p, ac_from_buttons (buttons));
|
||||
mp_editables->end_move (p, ac_from_buttons (buttons), mp_transaction.release ());
|
||||
return true;
|
||||
|
||||
}
|
||||
|
|
@ -269,9 +291,17 @@ MoveService::drag_cancel ()
|
|||
{
|
||||
m_shift = db::DPoint ();
|
||||
if (m_dragging) {
|
||||
|
||||
mp_editables->edit_cancel ();
|
||||
widget ()->ungrab_mouse (this);
|
||||
|
||||
m_dragging = false;
|
||||
|
||||
if (mp_transaction.get ()) {
|
||||
mp_transaction->cancel ();
|
||||
}
|
||||
mp_transaction.reset (0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,14 @@
|
|||
#ifndef HDR_layMove
|
||||
#define HDR_layMove
|
||||
|
||||
#include "dbManager.h"
|
||||
#include "layViewObject.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace lay {
|
||||
|
||||
class Editables;
|
||||
|
|
@ -46,6 +49,7 @@ public:
|
|||
~MoveService ();
|
||||
|
||||
virtual bool configure (const std::string &name, const std::string &value);
|
||||
bool begin_move (db::Transaction *transaction = 0);
|
||||
|
||||
private:
|
||||
virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
|
|
@ -58,13 +62,14 @@ private:
|
|||
virtual void drag_cancel ();
|
||||
virtual void deactivated ();
|
||||
|
||||
bool handle_dragging (const db::DPoint &p, unsigned int buttons);
|
||||
bool handle_dragging (const db::DPoint &p, unsigned int buttons, db::Transaction *transaction);
|
||||
|
||||
bool m_dragging;
|
||||
lay::Editables *mp_editables;
|
||||
lay::LayoutView *mp_view;
|
||||
double m_global_grid;
|
||||
db::DPoint m_shift;
|
||||
std::auto_ptr<db::Transaction> mp_transaction;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue