Re: What is the minimum number of lines to update a gui window without user clicking a button
Mr. James, This reply has 3 examples. The last time I sent you a complete solution you never indicated how it was insufficient, so please be sure read this entire message. The minimum amount of lines to use a TextView: //== Example 1 Begin // #include gtkmm.h int main(int argc, char *argv[]) { Glib::RefPtrGtk::Application app = Gtk::Application::create(argc, argv, com.example); Gtk::Window win; Gtk::TextView tv; tv.get_buffer()-set_text(Hello world); win.add(tv); win.show_all(); app-run(win); return 0; } //== Example 1 End // In your previous emails you have been expressing a desire to output the result of some long-lasting process to your window. As your problem was posed to the list it was a contrived problem that had no simple solution. Most GUI programs start operations by having the user interact with the window, either by pressing a button or selecting a menu item. Nonetheless, I have created another example program that performs a blocking operation in thread and changes the value of a TextView when the operation is finished. Note that in the quest for minimality I am utilizing some features of Gtkmm and C++ that are rarely shown in beginner examples (such as the ref-to-pointer and sigc::ref()). This example is 34 lines with no comments or whitespace. But I have gone ahead and added comments. //== Example 2 Begin // #include gtkmm.h #include unistd.h /* for sleep() */ void cleanup_thread(Glib::Threads::Thread *thread) { /* We must call Glib::Threads::Thread::join() in order to * correctly clean up the resource. */ if (thread) { thread-join(); thread = NULL; } } /* This function is called on a separate thread so as to avoid * blocking GTK+'s main loop. */ void blocking_operation(Glib::Dispatcher dispatcher) { /* This simulates a blocking process */ sleep(10); /* When the process is finished, we notify the GTK+ Main Loop by * using the dispatcher */ dispatcher(); } /* This function is called on GTK+'s main loop via a * Glib::Dispatcher */ void blocking_operation_finished(const Glib::RefPtrGtk::TextBuffer tb, Glib::Threads::Thread *thread) { cleanup_thread(thread); tb-set_text(Operation finished.); } int main(int argc, char *argv[]) { Glib::RefPtrGtk::Application app = Gtk::Application::create(argc, argv, com.example); Gtk::Window win; Gtk::TextView tv; Glib::RefPtrGtk::TextBuffer tb = tv.get_buffer(); Glib::Dispatcher dispatcher; Glib::Threads::Thread *blocking_operation_thread = NULL; /* Because I'm not using a class to encapsulate the above objects * and the methods (to keep it simple), I need to create * functors that are bound with these local variables. * * Note sigc::ref() is used here. Without it sigc::bind would try * to copy the dispatcher in this scope. We do not need to use * sigc::ref() on tb because RefPtr is a copyable pointer. */ sigc::slotvoid op_functor = sigc::bind(blocking_operation, sigc::ref(dispatcher)); sigc::slotvoid op_finished_functor = sigc::bind(blocking_operation_finished, tb, sigc::ref(blocking_operation_thread)); /* The dispatcher will be used when the operation has finished. * Here we set the function the dispatcher will call on the main * thread -- a.k.a. GTK+'s Main Loop. */ dispatcher.connect(op_finished_functor); /* Create a worker thread to perform the blocking_operation * function. */ blocking_operation_thread = Glib::Threads::Thread::create(op_functor); /* Now set the text in the buffer. */ tb-set_text(Operation started.); win.add(tv); win.show_all(); app-run(win); cleanup_thread(blocking_operation_thread); return 0; } //== Example 2 End // If one accepts the slight textual overhead of using a class, I have provided another solution. This allows more straightforward use of slots/functors, utilizing only sigc::mem_fun(). This example is 46 lines with no comments or whitespace. //== Example 3 Begin // #include gtkmm.h #include unistd.h /* for sleep() */ class Example { private: Glib::RefPtrGtk::Application app; Gtk::Windowwin; Gtk::TextView tv; Glib::RefPtrGtk::TextBuffer tb; Glib::Dispatcher dispatcher; Glib::Threads::Thread *thread; /* This function is called on a separate thread so as to avoid * blocking GTK+'s main loop. */ void blocking_operation() { /* This simulates a blocking process */ sleep(10); /* When the process is finished, we notify the GTK+ Main Loop by * using the dispatcher */ dispatcher(); }; /* This function is called on GTK+'s main loop via a *
Re: What is the minimum number of lines to update a gui window without user clicking a button
Thank you Andrew. I misunderstood your first message and am looking at it more in depth as well as your current post. You bring up a very important clarification I should make from my original post in this thread. I should not have counted the comments as part of the total number of lines. Sometimes I post something, and have an after though, but believe the general membership would see beyond my error. When excluding the important and very well documented comments of Kjell's example it comes up to nearly have my original number. The lines of code is about 235. Most of the confusion (for me) is the 11 widgets that, when I try to eliminate, breaks the code and I can't get it to work. I'm sure, eventually I'll figure it out, the same way if a person looked at the code for LibreOffice, and spent a lot of time analyzing and breaking it down. When I first started programming and was able to output a Hello World, I was happy. It worked. I made lots of changes and understood it. When I performed my first I/O it was just a minimum number of lines and did a strictly limited task. I was able to dissect it in one short session, then start using it productively in my crude programs. I'm trying to find this same strict focus with outputting and updating the gtkmm gui (without user input). If I can understand this, I'll have a foundation of which I could build upon. Kjell's example has everything I'm looking for, inclusive. But with my current understanding of gtkmm, it's too complex for me to be able to use. If all the widgets were eliminated and it just had a simple gui window, it would be a bit easier for a beginner to work with. At a glance it appears that you might have provided the needed solution (possibly in your first message last week). I apologize for missing some of the gist, but I will spend a lot of time studying in minute detail everything you have posted. I appreciate your asking me to point out what might be insufficient. I also appreciate Kjell's invitation for the community (including me) to comment on problems with his example. I'm sure, for experts there would hardly be any problems. It was very easy to compile. It has a lot included. However, for a novice, it's a bit overwhelming because it includes so much. A novice might have to keep everything intact to ensure that the code will compile, then try to figure out where to put his functions. As I mentioned, in my case, if I remove the buttons and progress bars, it becomes broken and I have to start back over with the full code and try a different approach. I would like to apologize to the community for being so new and using so many words to explain my problem. But if I use a minimum amount of words, someone might spend hours trying to help, but might come up with something that doesn't address the problem. So I' trying to make the problem clear, so that whatever time and energy anyone applies would more likely answer the question. Thanks! -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames On Fri, 2013-08-09 at 23:13 -0700, Andrew Potter wrote: Mr. James, This reply has 3 examples. The last time I sent you a complete solution you never indicated how it was insufficient, so please be sure read this entire message. The minimum amount of lines to use a TextView: //== Example 1 Begin // #include gtkmm.h int main(int argc, char *argv[]) { Glib::RefPtrGtk::Application app = Gtk::Application::create(argc, argv, com.example); Gtk::Window win; Gtk::TextView tv; tv.get_buffer()-set_text(Hello world); win.add(tv); win.show_all(); app-run(win); return 0; } //== Example 1 End // ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
Thanks you plenty, Andrew for giving so much consideration to my question. I'm really grateful for the generous comments and white spaces for clarity. I should have run this line on Kjell's code before making a reference to 400 lines: // cli command begin cat * | egrep -v ^\s+\*|^$|^/|^\s+/ | wc // cli command end Without the comments and white space, I'd be substantially more lost. At present your presentation is extremely clear and takes me far into resolution of my immediate hurtle. It compiles and works perfectly. I have a few more questions of which I'll try to organize and be clear when I post them. Some of them might be resolved by my dissecting what you've already posted with your clear documentation. By the way, one of the questions is, the significants of the com.example parameter of the Gtk::Application entry. Does the application use that information somewhere? When programing the Android, similar information is used for creating a default storage space. My other questions will relate to my effort to create a reusable gprint function that I can run as a gui counter part of the console cout. The overhead doesn't matter. Just as long as I can have a one or two liner in my function that will resemble: gprint(This is a new line of text); That will either append or replace the text in the current gui window. It might already be covered in the well documented code you've already shared. Hopefully I'll be able to at least understand what you've already shared well enough to get the ball substantially rolling. And oh yea, your example #1 was overwhelmingly clear, for a beginner. Maybe the gtkmm maintainers will consider using something like that for one of the beginner's hello world examples. I believe placing the hello world text on a button rather than some type of text screen leaves some gaps that takes a while to fill. It did in my case. By the way, I hope the gtkmm maintainers appreciate my input. I looked at a lot of gui projects for C++ before choosing gtkmm. I felt that I had chose the best documented and supported solution. The documentation is incredible! It's just that some of it is immediately over my head. Looking at how all the additional widgets falls into play is another lesson. I'm sure once I'm able to fully grasp the use of a single widget (in this case, the textview), the other examples will soon be a cinch to understand. Thanks! -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
I may be able to eventually figure out how to do it from your example, but at present it doesn't appear to have the ability to append text, except for an initial text and one addition. I'm trying to be able to arbitrarily update the text numerous times (just like you would with cout). I thought the dispatcher() function would work reusable like the gprint() function I'm trying to create. It appears to work correctly the first time. The other updates doesn't occur when the dispatcher() function is called. The gui window becomes non responsive and dimmed until all the functions are completed, then everything is showed at once. The window at the end of the operation becomes a normal gui. Kjell's example works exactly as intended, except that it has many widgets and I can't figure out how to remove the widgets without breaking the code. Also it requires a clicking of a button to start. I realize that, everything that a person needs is included in his example. My problem is being able to isolate a basic screen and an update. I know that I'll eventually understand it, and I'd be able to break it down for anyone else that might have problems with it, and reuse the many components in various applications. I realize how easy it would be for you and other experts to use his example. But I can't figure out where to put my function and output a single line to the gui, then perform a followup after some operations. I also appreciate the your reference to how complicated this task is. Hopefully I can contribute to making something complicated, easy for the next person. I added my example, using your code to demonstrate the problem that I'm having. I'm sure I'm misusing the dispatcher() function. But I don't see any other way to update the gui from your example. Thanks again for your contribution and input! // Code begin // -- #include gtkmm.h #include unistd.h /* for sleep() */ #include iostream using namespace std; class Example { string textdata = uninitilzed; private: Glib::RefPtrGtk::Application app; Gtk::Windowwin; Gtk::TextView tv; Glib::RefPtrGtk::TextBuffer tb; Glib::Dispatcher dispatcher; Glib::Threads::Thread *thread; /* This function is called on a separate thread so as to avoid * blocking GTK+'s main loop. */ void blocking_operation() { /* This simulates a blocking process */ sleep(5); textdata += First function is complete.\n; /* When the process is finished, we notify the GTK+ Main Loop by * using the dispatcher */ dispatcher(); sleep(5); textdata += Second function is completed.\n; dispatcher(); sleep(5); textdata += Third function is completed.\n; dispatcher(); sleep(5); textdata += Fourth function is completed.\n; textdata += This next funtion may take up to three hours to complete.\n; dispatcher(); sleep(60); textdata += Fifth function is completed.\n; dispatcher(); }; /* This function is called on GTK+'s main loop via a * Glib::Dispatcher */ void blocking_operation_finished() { cleanup_thread(); tb-set_text(textdata); }; void cleanup_thread() { /* We must call Glib::Threads::Thread::join() in order to * correctly clean up the resource. */ if (thread) { thread-join(); thread = NULL; } } public: ~Example() { /* This will prevent the Window from being closed while * the blocking operation is ongoing. */ cleanup_thread(); } Example(int argc, char *argv[]) : app(Gtk::Application::create(argc, argv, com.example)), tb(tv.get_buffer()), thread(NULL) { /* Create a slot (a.k.a. functor) to the * blocking_operation_finished() member function for the * dispatcher to execute. */ sigc::slotvoid op_finished_functor = sigc::mem_fun(this, Example::blocking_operation_finished); /* The dispatcher will be used when the operation has finished. * Here we set the function the dispatcher will call on the main * thread -- a.k.a. GTK+'s Main Loop. */ dispatcher.connect(op_finished_functor); /* Now set the text in the buffer. */ textdata = Starting application.\n; tb-set_text(textdata); win.add(tv); win.show_all(); } void run() { /* Create a slot to the blocking_operation() member function * to pass to Glib::Threads::Thread::create(). */ sigc::slotvoid op_functor = sigc::mem_fun(this, Example::blocking_operation); /* Create a worker thread to perform the blocking_operation * function. */ thread =
Re: What is the minimum number of lines to update a gui window without user clicking a button
On Sat, 10 Aug 2013 05:43:42 -0400 L. D. James lja...@apollo3.com wrote: When I first started programming and was able to output a Hello World, I was happy. It worked. I made lots of changes and understood it. When I performed my first I/O it was just a minimum number of lines and did a strictly limited task. I was able to dissect it in one short session, then start using it productively in my crude programs. I'm trying to find this same strict focus with outputting and updating the gtkmm gui (without user input). If I can understand this, I'll have a foundation of which I could build upon. The point you may not understand is that you would rarely if ever want to do this in a simple real-world application, and particularly where your simple application is a learning exercise about using GTK+. GTK+ is, like almost all other GUI toolkits, event driven, and runs in a main loop. Therefore, if text arrives which you want to put in a widget, it would normally arrive as an event. If you are monitoring I/O, you would use Glib::signal_io().connect() to connect a file descriptor or Glib::IOChannel object to the main loop. Similar convenience functions are available for timeouts and idle handlers. I would strongly advise you not to get involved in using threads until you have more programming experience. Chris ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
Thanks for the advise, Chris I already have a lot of applications of which I hope to put into place for my clients who see a monster when they see a text screen. Many of the task are very simple task, such as connecting to a VPN and giving a status of each step, so that if any component failed, or got stuck, the client could see it and not be turned off by seeing the text screen. I try to get people not to be so turned off by the text screen, but in this world, they are. Also, I'm making some of the task as launchers from the Ubuntu Unity button. The console screen doesn't look appealing, even to me. To many people (not to me of course, because I almost always work with a console terminal and do most of my work remotely) when they see a console screen that think that is evidence that something has crashed, or something bad is happening. I'm taking your advise, and had begun doing a lot of studying before I starting asking my questions and asking for help. I know that I could eventually figure all this out without help. But it'd take me years, whereas I was hoping that there might be some users of this mailing list, such as Alan and Andrew that might not mind parting with some of their experience and helping me over some of my hurtles. I don't mean to aggravate the group with my questions. I assure you, I won't be novice in this matter for long. I'm a very fast learner and at present have some gaps. In my research some new users have been given the opposite advice of what you had suggested to me. Some users have been told to study gtkmm and become familiar with this interface which had done a lot of work with the lower level of gtk and gtk++. They might waste a lot of time trying to reinvent the wheel ( http://stackoverflow.com/questions/3448937/class-extending-gtkwindow ) for something already provided if they try to do it with gtk instead of learning gtkmm. Of course, you may be right, in that gtkmm has not taken into account that a person might want to simply update the gui. I believe there is a need in this capacity. Kjell mention in his message that, the need is there, and the solution is provided, but didn't have any examples. He has started to fill the void. I already mentioned that I debated whether to learn gtkmm or to go a different direction. I even considered as you just suggested in working with gtk instead of gtkmm, but took the advise of another expert to learn how to use the gtkmm interface, rather than doing everything from a low level and reinventing the wheel. I can tell from Kjell's message that what I'm trying to do is already implemented in gtkmm. At present using it, just isn't all that clear. I hope to contribute to the group by assisting in helping things to be clearer, and to help close gaps that might exist. I can already easily update the console with a status without user input. I believe there is also merit in updating agui window without user input, of which, I appreciate the few people who have taking the time to understand the problem and investigated it. As far as realworld applications, most applications have some element of processing and outputting a status to the user without the user having to sit at the concole and constantly click buttons. I really appreciate your input and suggestions. But I believe you're misunderstanding the question. I realize buttons and user input is an important part of applications. However, at present, I would just like to be able to output notifications to my clients into a gui window without my application having to be hung until they come to the computer and click a button. The purpose of what I'm trying to do is allow the user to know at which stage the application has progressed, and to be able to report to me any messages, errors status updates that I present. As far as the VPN connection, if my program is waiting for an internet connection, it will state that. When it has the connection, without the user having to come back and tell the program to continue, it will just update, internet connection established, the remote host is currently off line... will try again in 5 minutes. The present console program eventually says, vpn connection established now configuring the local routing. I have many applications (or c++ routines) to do things such as that. They all output to a black screen. They frighten my customers. I hope to find a simple way of outputting the status to a friendly gui window. I don't mean to sound ungrateful with my reply, but I'm hoping that I'm clarifying what I'm trying to do, and that it does have some merit. -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames On Sat, 2013-08-10 at 13:54 +0100, Chris Vine wrote: On Sat, 10 Aug 2013 05:43:42 -0400 L. D. James lja...@apollo3.com wrote: When I first started programming and was able to output a Hello World, I was happy. It worked. I made lots of changes and understood it. When I performed my first
Re: What is the minimum number of lines to update a gui window without user clicking a button
On Sat, 10 Aug 2013 09:32:58 -0400 L. D. James lja...@apollo3.com wrote: [snip] As far as realworld applications, most applications have some element of processing and outputting a status to the user without the user having to sit at the concole and constantly click buttons. I really appreciate your input and suggestions. But I believe you're misunderstanding the question. I realize buttons and user input is an important part of applications. However, at present, I would just like to be able to output notifications to my clients into a gui window without my application having to be hung until they come to the computer and click a button. The purpose of what I'm trying to do is allow the user to know at which stage the application has progressed, and to be able to report to me any messages, errors status updates that I present. As far as the VPN connection, if my program is waiting for an internet connection, it will state that. When it has the connection, without the user having to come back and tell the program to continue, it will just update, internet connection established, the remote host is currently off line... will try again in 5 minutes. The present console program eventually says, vpn connection established now configuring the local routing. I have many applications (or c++ routines) to do things such as that. They all output to a black screen. They frighten my customers. I hope to find a simple way of outputting the status to a friendly gui window. I don't mean to sound ungrateful with my reply, but I'm hoping that I'm clarifying what I'm trying to do, and that it does have some merit. Your posts are no doubt highly meritorious but I am afraid they are not offering much clarification. You would probably make your point better if you shortened your posts by roughly an order of magnitude. However, after cutting through the dense undergrowth, I still think you have failed to understand how programs using event loops work. If the program is not just running a single batch of instructions, it has to have a loop in there somewhere, which is blocking until there is something to process. The simplest loop for your console program would involve blocking on select() or poll(), for which purpose presumably you must have a file descriptor to poll on. In that case, as I said, you can do the same with Glib::signal_io().connect(). Or maybe you are polling using timeouts, in which case the equivalent for gtkmm is Glib::signal_timeout().connect(). Why not get to the heart of the matter, and post a short compilable console program, cut down from the ones which you appear to have written for monitoring VPNs, but of no more than 50 lines, and we can tell you how to do the same using a graphical interface. Chris ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
On Sat, 2013-08-10 at 16:45 +0100, Chris Vine wrote: Your posts are no doubt highly meritorious but I am afraid they are not offering much clarification. You would probably make your point better if you shortened your posts by roughly an order of magnitude. However, after cutting through the dense undergrowth, I still think you have failed to understand how programs using event loops work. If the program is not just running a single batch of instructions, it has to have a loop in there somewhere, which is blocking until there is something to process. The simplest loop for your console program would involve blocking on select() or poll(), for which purpose presumably you must have a file descriptor to poll on. In that case, as I said, you can do the same with Glib::signal_io().connect(). Or maybe you are polling using timeouts, in which case the equivalent for gtkmm is Glib::signal_timeout().connect(). Why not get to the heart of the matter, and post a short compilable console program, cut down from the ones which you appear to have written for monitoring VPNs, but of no more than 50 lines, and we can tell you how to do the same using a graphical interface. Chris I'll accept the admonishment. I'm sorry for the verbose description. It appears that you're starting to get the gist. I appreciate your asking me to expound with an example. The VPN application currently have 500 lines. I'll strip it down to 50, making sure it retains functionality and post it. One of the reasons I didn't post it before, but posted sleep(10) to represent the application was doing something, because the program is designed to make changes to the system. But, I'm sure I'll be able to comment and have such a flow that you might be able to easily follow it just by looking at it, or, on your own, comment out the parts that makes changes. Thanks! -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
On Sat, 10 Aug 2013 12:16:16 -0400 L. D. James lja...@apollo3.com wrote: [snip] The VPN application currently have 500 lines. I'll strip it down to 50, making sure it retains functionality and post it. One of the reasons I didn't post it before, but posted sleep(10) to represent the application was doing something, because the program is designed to make changes to the system. But, I'm sure I'll be able to comment and have such a flow that you might be able to easily follow it just by looking at it, or, on your own, comment out the parts that makes changes. If an outline of your code just consists of: void check_stuff() { if (vpn_connections_changed()) std::cout XXX changed\n; } int main(int argc, char* argv[]) { for (;;) { sleep(10); check_stuff(); } return 0; } Then in gtkmm this just becomes: bool check_stuff() { if (vpn_connections_changed()) std::cout XXX changed\n; return true; } int main(int argc, char* argv[]) { Gtk::Main app(argc, argv); Glib::signal_timeout().connect_seconds(sigc::ptr_fun(check_stuff), 10); app.run(); return 0; } You can go from there and add your graphical interface to check_stuff() in place of the call to std::cout. You might, for example, want to display a Gtk::MessageDialog object. With gtkmm-3.0, you might want to use Gtk::Application instead of Gtk::Main. But first things first. Chris ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
dispatcher() causes the function blocking_operation_finished() to be called, which in turn calls Glib::Threads::Thread::join(). join() will block the GTK+ main loop until the thread has completely finished (i.e. blocking_operation() has returned). Calling dispatcher() more than once means that blocking_operation_finished() will be called more than once. I hope you can understand why that is wrong. Here is the next step in our example series. I have chosen to abstract the ability to send parameters a function on the main thread through the use of the CallbackDispatcher class. Its usage is simple: create a functor that accepts zero arguments and pass it to send(). That functor will be executed on the main loop. A zero argument functor may be created from any function by using sigc::bind. I have also chosen to use a Gtk::Label for this example, so as to sidestep the issue of bug 495762. Using a custom wrapper around Glib::Dispatcher to teach a newbie is, perhaps, bad etiquette. But the utility of this wrapper in sending progress back to the main loop has been so great in my experience that I can't resist. //== Example 4 Begin // #include gtkmm.h #include unistd.h /* for sleep() */ #include queue class CallbackDispatcher { public: CallbackDispatcher() { dispatcher.connect(sigc::mem_fun(this, CallbackDispatcher::on_dispatch)); } typedef sigc::slotvoid Message; void send(Message msg) { Glib::Threads::Mutex::Lock lock(mutex); queue.push(msg); dispatcher(); } private: /* CallbackDispatcher may not be copied, so we must hide these * constructors */ CallbackDispatcher(const CallbackDispatcher); CallbackDispatcher operator=(const CallbackDispatcher); Glib::Threads::Mutex mutex; std::queueMessage queue; Glib::Dispatcher dispatcher; void on_dispatch() { Glib::Threads::Mutex::Lock lock(mutex); while (!queue.empty()) { queue.front()(); queue.pop(); } } }; class Example { private: Glib::RefPtrGtk::Application app; Gtk::Windowwin; Gtk::Label label; CallbackDispatcher callback_dispatcher; Glib::Threads::Thread *thread; void report_progress(const Glib::ustring str) { callback_dispatcher.send(sigc::bind(sigc::mem_fun(label, Gtk::Label::set_text), str)); } /* This function is called on a separate thread so as to avoid * blocking GTK+'s main loop. */ void blocking_operation() { /* This simulates a blocking process */ sleep(5); report_progress(5% complete.); sleep(5); report_progress(15% complete.); sleep(5); report_progress(35% complete.); sleep(5); report_progress(55% complete.); sleep(5); report_progress(75% complete.); sleep(5); report_progress(95% complete.); sleep(5); report_progress(100% complete.); /* When the process is finished, we notify the GTK+ Main Loop by * using the dispatcher */ callback_dispatcher.send(sigc::mem_fun(this, Example::blocking_operation_finished)); }; /* This function is called on GTK+'s main loop via a * Glib::Dispatcher */ void blocking_operation_finished() { cleanup_thread(); label.set_text(Operation finished.); }; void cleanup_thread() { /* We must call Glib::Threads::Thread::join() in order to * correctly clean up the resource. */ if (thread) { thread-join(); thread = NULL; } } public: ~Example() { /* This will prevent the Window from being closed while * the blocking operation is ongoing. */ cleanup_thread(); } Example(int argc, char *argv[]) : app(Gtk::Application::create(argc, argv, com.example)), label(), thread(NULL) { win.add(label); win.show_all(); } void run() { /* Create a slot to the blocking_operation() member function * to pass to Glib::Threads::Thread::create(). */ sigc::slotvoid op_functor = sigc::mem_fun(this, Example::blocking_operation); /* Create a worker thread to perform the blocking_operation * function. */ thread = Glib::Threads::Thread::create(op_functor); /* Now set the text in the buffer. */ label.set_text(Operation started.); app-run(win); } }; int main(int argc, char *argv[]) { Example example(argc, argv); example.run(); return 0; } //== Example 4 End // On Sat, Aug 10, 2013 at 5:39 AM, L. D. James lja...@apollo3.com wrote: I may be able to eventually figure out how to do it from your example, but at present it doesn't appear to have the ability to append text, except for an initial text and one addition.
Re: What is the minimum number of lines to update a gui window without user clicking a button
On 08/10/2013 11:45 AM, Chris Vine wrote: Your posts are no doubt highly meritorious but I am afraid they are not offering much clarification. You would probably make your point better if you shortened your posts by roughly an order of magnitude. However, after cutting through the dense undergrowth, I still think you have failed to understand how programs using event loops work. If the program is not just running a single batch of instructions, it has to have a loop in there somewhere, which is blocking until there is something to process. The simplest loop for your console program would involve blocking on select() or poll(), for which purpose presumably you must have a file descriptor to poll on. In that case, as I said, you can do the same with Glib::signal_io().connect(). Or maybe you are polling using timeouts, in which case the equivalent for gtkmm is Glib::signal_timeout().connect(). Chris, thanks again for your interest in my question. I apologize for the delayed response, as I was on a support call for most of the day. When I got back I trimmed down 500 lines of code to the example below. This is 48 lines of my vpn connection routine. It's 48 out of the 500 line application. In those 48 lines I have 4 lines outputting to the console. I would like for those lines to output to a gui window. Those 4 lines are just some of the actually 25 lines of status that will be output in the course of running the application. While it's running and checking the connection it outputs either starts * or dots . at 10 second interval while it checks some of the file and connection status. // code begin // - #include iostream #include fstream #include unistd.h #include string using namespace std; int main(int argc, char* argv[]) { string ret; string server; string command; string runit(string c); setuid(0); server = argv[1]; string peerentry = /etc/ppp/peers/ + server; command = ls + peerentry; ret = runit(command); if (ret != peerentry){ cout Problems locating server: server endl; // console out return 1; } string filetest = /var/run/ppp- + server + .pid; ifstream myfile(filetest.c_str()); if (myfile.is_open()){ cout Connection is in effect endl; // console out myfile.close(); } else{ cout Connecting to... server endl; // console out command = pppd call + server; ret = runit(command); cout Results: [ ret ] endl; // console out } return 0; } string runit(std::string c){ string lret = ; c += 21; FILE *in; char buff[512]; if (!(in = popen(c.c_str(), r))){ return lret; } while (fgets(buff, sizeof(buff), in) != NULL){ lret += buff; } pclose(in); return lret; } // - // code end -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
Thanks, Andrew. I'll study and compile your example and comment on if it's the gist of what I'm trying to accomplish. Looking at it, it appears like it will work. However, I'm not trying to send progress statistics, I'm just trying to send general information. Some of my programs sorts and index, and archives email messages. It may send a message to the console that there are currently 1000 emails about to be sorted. Then it's cross reference the headers with messages addresses in the users' address book. It'll output to the console that there are 500 email addresses that are not in the address book and sort them into a separate area. These are all messages to a black console. Many of my customers are used to seeing the black screen. I'm just want to take my 10's of programs and have many of them output the text to a graphics screen rather than the console screen. I will find it convenient to create a function call gprint(). Where I have cout ether replace the cout with gprint or use both, but the gprint() will just update a gui with a message that currently goes to a black screen. I apologize for repeating this so much. I have read numerous times the code of conduct for this forum. I'm trying to comply and not to aggravate the membership with repetition and verbose messages. But most of the comments I get gives me the impression that the members are misunderstanding what I'm looking for. Just like gtkmm is a convenient wrapper for gtk++, I hope to make a gprint() routine to be a wapper for however many lines it takes to create a gui window and be able to run a one or two liner to please a new message to that gui window. At a glance it appears that the code you have below might have the gist, even though it's referencing percentages of progress instead of regular text output informing the user what the application is currently doing, and what it might do next, or informing the user of any errors or problems it might be encountering. I really apologize for the many words to try to be clear. I just posted an example of one of my C++ applications. I have done it with Java and might post a Java application that perfectly fits the bill (as for as having a window and sending updates to that window). The problem with the Java, is that you can't set the suid bit for some of the routines that needs to be run as root. I was doing that with a C++ wrapper to call the Java program. But now, I'm trying to do it all in C++ with gtkmm. Once I develop the gprint() function, I'm sure this will totally make things clear. I'm sure that many will find it a convenient resource. -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames On Sat, 2013-08-10 at 12:23 -0700, Andrew Potter wrote: dispatcher() causes the function blocking_operation_finished() to be called, which in turn calls Glib::Threads::Thread::join(). join() will block the GTK+ main loop until the thread has completely finished (i.e. blocking_operation() has returned). Calling dispatcher() more than once means that blocking_operation_finished() will be called more than once. I hope you can understand why that is wrong. Here is the next step in our example series. I have chosen to abstract the ability to send parameters a function on the main thread through the use of the CallbackDispatcher class. Its usage is simple: create a functor that accepts zero arguments and pass it to send(). That functor will be executed on the main loop. A zero argument functor may be created from any function by using sigc::bind. I have also chosen to use a Gtk::Label for this example, so as to sidestep the issue of bug 495762. Using a custom wrapper around Glib::Dispatcher to teach a newbie is, perhaps, bad etiquette. But the utility of this wrapper in sending progress back to the main loop has been so great in my experience that I can't resist. //== Example 4 Begin // #include gtkmm.h #include unistd.h /* for sleep() */ #include queue class CallbackDispatcher { public: CallbackDispatcher() { dispatcher.connect(sigc::mem_fun(this, CallbackDispatcher::on_dispatch)); } typedef sigc::slotvoid Message; void send(Message msg) { Glib::Threads::Mutex::Lock lock(mutex); queue.push(msg); dispatcher(); } private: /* CallbackDispatcher may not be copied, so we must hide these * constructors */ CallbackDispatcher(const CallbackDispatcher); CallbackDispatcher operator=(const CallbackDispatcher); Glib::Threads::Mutex mutex; std::queueMessage queue; Glib::Dispatcher dispatcher; void on_dispatch() { Glib::Threads::Mutex::Lock lock(mutex); while (!queue.empty()) { queue.front()(); queue.pop(); } } }; class Example { private: Glib::RefPtrGtk::Application app; Gtk::Windowwin; Gtk::Label
Re: What is the minimum number of lines to update a gui window without user clicking a button
On Sat, 10 Aug 2013 17:53:41 -0400 L. D. James lja...@apollo3.com wrote: [snip] Chris, thanks again for your interest in my question. I apologize for the delayed response, as I was on a support call for most of the day. When I got back I trimmed down 500 lines of code to the example below. This is 48 lines of my vpn connection routine. It's 48 out of the 500 line application. In those 48 lines I have 4 lines outputting to the console. I would like for those lines to output to a gui window. Those 4 lines are just some of the actually 25 lines of status that will be output in the course of running the application. While it's running and checking the connection it outputs either starts * or dots . at 10 second interval while it checks some of the file and connection status. // code begin // - #include iostream #include fstream #include unistd.h #include string using namespace std; int main(int argc, char* argv[]) { string ret; string server; string command; string runit(string c); setuid(0); server = argv[1]; string peerentry = /etc/ppp/peers/ + server; command = ls + peerentry; ret = runit(command); if (ret != peerentry){ cout Problems locating server: server endl; // console out return 1; } string filetest = /var/run/ppp- + server + .pid; ifstream myfile(filetest.c_str()); if (myfile.is_open()){ cout Connection is in effect endl; // console out myfile.close(); } else{ cout Connecting to... server endl; // console out command = pppd call + server; ret = runit(command); cout Results: [ ret ] endl; // console out } return 0; } string runit(std::string c){ string lret = ; c += 21; FILE *in; char buff[512]; if (!(in = popen(c.c_str(), r))){ return lret; } while (fgets(buff, sizeof(buff), in) != NULL){ lret += buff; } pclose(in); return lret; } // - // code end This appears to be just a batch job calling popen() which brings up a ppp connection. There is no program loop anywhere and the while loop for fgets() in runit() will block until EOF is reached, which equates to the call to pppd ending and the process in which it is running closing its stdout. Presumably you run this as a cron job, or something like that? Or, since you say, while it's running and checking the connection it outputs either starts '*' or dots '.' at 10 second interval while it checks some of the file and connection status, possibly you have excised the loop logic, which is the interesting part for present purposes. (As it happens, it will not compile because the prototype for runit() is not in namespace scope, but that is no doubt just a matter of transcription.) To call up an executable (in this case pppd) in this kind of usage using glib you would normally use Glib::spawn_async_with_pipes() and connect to the standard_output and standard_error file descriptors with Glib::signal_io().connect(). The problem you have got here though is that you call setuid(0) on a binary which presumably has its suid bit set in order to launch pppd. You should definitely not do that directly with a GTK+ program. You would need to have a small wrapper with suid set which calls up pppd, which is launched by your GTK+ program using Glib::spawn_async_with_pipes(). (Yuck.) As it happens, if you want a short cut for a batch job like this which provides a GTK+ user interface, I would consider a shell script and zenity, which is what zenity was intended for. A google search will tell you more. However you would still need to circumvent your setuid problem. Chris ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
On 08/10/2013 07:09 PM, Chris Vine wrote: This appears to be just a batch job calling popen() which brings up a ppp connection. There is no program loop anywhere and the while loop for fgets() in runit() will block until EOF is reached, which equates to the call to pppd ending and the process in which it is running closing its stdout. Presumably you run this as a cron job, or something like that? Or, since you say, while it's running and checking the connection it outputs either starts '*' or dots '.' at 10 second interval while it checks some of the file and connection status, possibly you have excised the loop logic, which is the interesting part for present purposes. (As it happens, it will not compile because the prototype for runit() is not in namespace scope, but that is no doubt just a matter of transcription.) To call up an executable (in this case pppd) in this kind of usage using glib you would normally use Glib::spawn_async_with_pipes() and connect to the standard_output and standard_error file descriptors with Glib::signal_io().connect(). The problem you have got here though is that you call setuid(0) on a binary which presumably has its suid bit set in order to launch pppd. You should definitely not do that directly with a GTK+ program. You would need to have a small wrapper with suid set which calls up pppd, which is launched by your GTK+ program using Glib::spawn_async_with_pipes(). (Yuck.) As it happens, if you want a short cut for a batch job like this which provides a GTK+ user interface, I would consider a shell script and zenity, which is what zenity was intended for. A google search will tell you more. However you would still need to circumvent your setuid problem. Chris Hi, Chris. I stripped down a 500 line C++ program and included some system calls to give you and example of my many C++ programs. Many C++ programs use calls to the system shell. I can tell that happening with a number of driver installations. This application would not work as a bash script. I mentioned to you that you can not set the suid bit on a bash script. I'm familiar with cron jobs, and have no problems with cronjobs. In fact some of my applications are run by cron. The particular VPN connection application is run currently added to the Ubuntu dash and shows a black screen for the status when it's run. By the way, there are gui applications for batch files, perl files and just about any other programming concept. I appreciate your interest and your questions and suggestions. I understand that I don't have to use or learn gtkmm. But I hope you don't mind my interest in the facility. Some of my applications do not use any system calls. Some of them use some system calls. But I would like for most of them to output to a gui window where than a console. I understand how complicated you think this will be. But it can be done with C++ just as with just about any programming application. By the way, the program does compile. I've already started to add the gui interface. I did it with the gtk label with the help of Alan. I posted the example in a different thread. I ran into problems when I tried to change the label widget into a textview widget because I was having problems understanding the full gist of the gtkmm tools. When Kjell posted his resolution, I saw the light. So I started this thread on trying to break down Kjell's program into components (namely to eliminated the unneeded widgets). I'm getting there with some of the in-between the line suggestions from this new thread. I'm starting to understand more and more how to use gtkmm, of which I'm trying to do. I really don't think it's as complicated and some users are suggesting. I believe it's just a matter of getting a grip of a few vague concepts. While I'm having problems just sending text to a window, you're suggesting that I dive figure and use gtkmm for my other calls. I might get to that at some time. But at present, I just want to use gtkmm to output to a gui screen instead of a black screen. -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
compiler error
I am trying to compiler gtkmm2.99, Some some packages, they don't like gtk3.* I am not sure this is because that I am using a newer compiler or not: cal/include/c++/4.8.1 -MT event.lo -MD -MP -MF .deps/event.Tpo -c -o event.lo event.cc libtool: compile: g++ -DHAVE_CONFIG_H -I.. -I../.. -DG_LOG_DOMAIN= \gdkmm\ -DGDKMM_BUILD=1 -pthread -pthread -I/usr/local/include/giomm-2.4 -I/usr/local/lib/giomm-2.4/include -I/usr/local/include/glibmm-2.4 -I/usr/local/lib/glibmm-2.4/include -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/local/include/sigc++-2.0 -I/usr/local/lib/sigc++-2.0/include -I/usr/local/include/pangomm-1.4 -I/usr/local/lib/pangomm-1.4/include -I/usr/local/include/cairomm-1.0 -I/usr/local/lib/cairomm-1.0/include -I/usr/local/include/pango-1.0 -I/usr/local/include/cairo -I/usr/local/include -I/usr/local/include/freetype2 -I/usr/local/include/gtk-3.0 -I/usr/local/include/atk-1.0 -I/usr/local/include/gio-unix-2.0/ -I/usr/local/include/gdk-pixbuf-2.0 -I/usr/local/include/harfbuzz -I/usr/include/pixman-1 -I/usr/include/libpng12 -I/usr/include/at-spi2-atk/2.0 -Wall -I/usr/local/include/boost -I/usr/local/include/c++/4.8.1 -MT event.lo -MD -MP -MF .deps/event.Tpo -c event.cc -fPIC -DPIC -o .libs/event.o event.cc: In static member function ‘static GType Glib::ValueGdk::ExtensionMode::value_type()’: event.cc:51:38: error: ‘gdk_extension_mode_get_type’ was not declared in this scope return gdk_extension_mode_get_type(); ^ event.cc:52:1: warning: control reaches end of non-void function [-Wreturn-type] } Kemin ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
On Sat, 10 Aug 2013 19:41:33 -0400 L. D. James lja...@apollo3.com wrote: [snip] While I'm having problems just sending text to a window, you're suggesting that I dive figure and use gtkmm for my other calls. I might get to that at some time. But at present, I just want to use gtkmm to output to a gui screen instead of a black screen. You keep missing the point. If you don't want to use zenity, as I said use Glib::spawn_async_with_pipes() and Glib::signal_io().connect(). That is the correct way to do it. Chris ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list
Re: What is the minimum number of lines to update a gui window without user clicking a button
Thanks, Chris. I may end up using Glib::spawn_async (but I it doesn't appear to be a call for updating text to a gui window) and I may end up using Glib::signal_io().connect()) to send text to the gui window. This is the first time i see these as ways of updating the gui. Keep in mind that what I'm trying to do is develop a reusable function that I have named, gprint(). I'm sure I'm just about close enough to post a prototype by tomorrow. Thanks again for all your contributions, and patient for my newness with using a gtkmm widgets. My only problem with Kjell's example if being able to remove the unwanted ones. My problem with Alan's solution (which worked perfect) was changing it from label to textview (because of some gaps I was having at the time). I finally got it figured out how to change the widget from label to text view, now I'm trying to implement the gprint() function. I have it in place, but it's not clean enough to post it for comments yet. -- L. James -- L. D. James lja...@apollo3.com www.apollo3.com/~ljames On Sun, 2013-08-11 at 01:20 +0100, Chris Vine wrote: On Sat, 10 Aug 2013 19:41:33 -0400 L. D. James lja...@apollo3.com wrote: [snip] While I'm having problems just sending text to a window, you're suggesting that I dive figure and use gtkmm for my other calls. I might get to that at some time. But at present, I just want to use gtkmm to output to a gui screen instead of a black screen. You keep missing the point. If you don't want to use zenity, as I said use Glib::spawn_async_with_pipes() and Glib::signal_io().connect(). That is the correct way to do it. Chris ___ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list