Forum

Results 1 to 11 of 11
  1. #1
    Join Date
    August 2014
    Posts
    27

    A simple input box

    I'd like for a simple input box to appear after right clicking on client and then selecting one of the plugins menu items. That input would obviously be saved in a variable and then later used.
    So basically what I require is for someone to check what I've attempted and tell me which way seems the smartest. And then help me out please.
    I personally think it's the first option - requires the least work, least messy and should do exactly what needed.

    This is what I've attempted:
    I followed instructions given in this post here http://forum.teamspeak.com/showthrea...320#post400320.
    I checked the documentation (which is veeeeeery rich with detail). After some search I found the QInputDialog, which looks like exactly what I need. Since the sample code was... rich, I looked up a guide, which showed how to implement this kind of thing without any additional uselessness (ok, maybe not 100%, but still a lot cleaner). After fixing numerous linking errors, (including mysterious metacast and metaobject issues), I finally got it compiled. But as soon as I select the menu item, entire client just crashes.

    However, the story doesn't stop here. I've also tried Visual Studio's own resource dialog and Qt's solution. For Visual Studio, I followed this wonderful guide. Although it didn't look exactly what was needed, I thought that getting any windows to appear would be a nice start and I could modify the window later on to suit my needs. I take the code that can be seen in the end, make little adjustments to blend it into my project, acquire HINSTANCE with GetModuleInstance(NULL). Everything compiled nicely, but when I try it, the window doesn't appear. It does in testing environment though (different project). Everything seems to be in order; there are no errors, no warnings, no any sign of possible malfunction but alas, no window. (quick side note, if do like this: HINSTANCE hinst = GetModuleInstance; and then attempt to print "hinst" with printf as a string, it creates a mysterious "BEEP" sound).

    I've also attempted as Chris suggested in the post previously linked. I made the box in Qt Designer, I saved the .ui file. I converted it with the uic utility, which only gave me code that looked like header code, so I put it into header file. It didn't give me any .cpp files though. It actually refuses to give any files itself, because if any argument is given to uic utility, it simply never stops doing whatever it is doing. Anyway, I get it included in my project and create an object of the class defined in that newly created header. However, something must have gone wrong, because when I attempted to use QDialog:pen(), it complained it needs a pointer. I did work quite a lot with this, but I can't remember much what I did with it. I switched a lot between VS resource and this solution whenever I had an idea of what could work. Anyway, this also didn't seem exactly what I wanted anyway.

    Should I post the code files as well? In other threads it's not usually done, but I guess in this case it might be useful?

  2. #2
    Join Date
    October 2012
    Location
    Germany
    Posts
    553
    One might argue some other threads would've been quite shorter with the source available from the beginning

    Well, what can be said for now.
    That the result you got from the designer file is just a header is probably right, it just puts the whole class in there.
    I say probably since I tried Qt Creator for...well my Qt Projects early on and use it for those Qt cross plattform projects since and it's all a little less problematic to set up over there (surprise).
    Note that this way of using Designer is absolutely optional, this stuff can obviously be coded traditionally just as well, it's just a preference depending on the user (e.g. designer vs. coder) and widget type (complex, dynamic or static etc.).
    I'd avoid the Nokia docs, Nokia got out of Qt before 5.x (Elop, need one say more).

    The Input Dialog should be pretty much like those few lines of the qt docs state, like
    Code:
    bool ok;
        QString text = QInputDialog::getText(this, tr("QInputDialog::getText()"),
                                             tr("User name:"), QLineEdit::Normal,
                                             QDir::home().dirName(), &ok);
        if (ok && !text.isEmpty())
            textLabel->setText(text);
    One thing that springs to mind is that this static variant is blocking, waiting for the return value. Wouldn't count on the plugin API being ok with that. You might wanna look at open(), show(), exec() and investigate if constructing the dialog and using open() (returning immediately) will solve that.

    The probably closest example to peek at in my source would be the message box of my updater:
    https://github.com/thorwe/CrossTalk/...dater.cpp#L127
    As you can see, in total contradiction to my advice I end up using exec() over there and the comments point out I had a little fun with that part, too It's been a while, not sure if manually moving this to the gui thread was necessary. Having it as a child of the mainwindow however has some slight benefits like appearing in center of the application.

    Alternatively, some mysteriousness might not be entirely fixed

    Can't say anything about winapi in TS, my plugin was planned as cross plattform from the very beginning (now, if I would actually compile it for all plattforms...).

  3. #3
    Join Date
    August 2014
    Posts
    27
    Hah, you are right, generally it would have been shorter, but right now, if I had included all three sources, it would have been even longer, so I figured I'll show what and how I've attempted.
    I finally got time to come back to this and I figured out why it's crashing. It's because of the line where I create an object of that dialog class.

    Code:
    Dialoginput dialog_i;
    If I have this, Teamspeak 3 client will crash immediately after start up.
    This is what's written in .dmp file
    "The thread tried to read from or write to a virtual address for which it does not have the appropriate access." (which is what gets written into every single .dmp file I've ever seen). Usually when I get this, it means I screwed up with pointers somewhere, but right now I'm quite buffled.

    This is what the .h file looks like.
    Code:
    #ifndef INPUT_DIALOG_H
    #define INPUT_DIALOG_H
     
    #include <QtWidgets\qdialog.h>
    #include <QtWidgets\qpushbutton.h>
    #include <QtWidgets\qinputdialog.h>
    #include <QtWidgets\qlabel.h>
     
    class Dialoginput : public QDialog
    {
        Q_OBJECT
     
    public:
    	Dialoginput(QWidget *parent = 0);
        ~Dialoginput();
    private slots:
    	void setText();
    private:
    	QPushButton *button;		
    	QLabel *label; 
    };
     
    #endif // INPUT_DIALOG_H
    Any ideas? I browsed your code a bit, it looks like you are creating objects in the same way.

    One thing that springs to mind is that this static variant is blocking, waiting for the return value. Wouldn't count on the plugin API being ok with that.
    Sleep() counts as blocking as well, right? I've used that without problems.
    Last edited by Birman; January 15th, 2015 at 06:34 PM.

  4. #4
    Join Date
    October 2012
    Location
    Germany
    Posts
    553
    From my understanding, and I might be wrong about that, all those api function live in the main application's specific threads. Hence, stuff might be ok on one place and cause trouble on another. Given that extern ownership, I try to avoid how can I describe it, I try to not get in the way and expect the worst ;D
    That's why, apart from that code-only one liner example from my last reply, I don't block.
    settings_duck line 65ff
    Code:
    if (config)
                    config.data()->activateWindow();
                else
                {
                    ConfigDucking* p_config = new ConfigDucking(TSHelpers::GetMainWindow());  //has delete on close attribute
    ....
    config= p_config;
    First part checks if config is already there, if so, open.
    else instantiate, rest is done inside config_ducking.
    Safe pointer to config in settings class (should actually be redundant with the delete on close window attribute).

    So, I don't need to block what I would've to do with Dialoginput dialog_i; which would be destroyed when the function is done.

    Dunno if that's the issue though, there's not much to tell by the header.
    I suspect either the lines after instantiation or the .cpp would shed some light.

  5. #5
    Join Date
    August 2014
    Posts
    27
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    #include <iostream>
    #include "public_errors.h"
    #include "public_errors_rare.h"
    #include "public_definitions.h"
    #include "public_rare_definitions.h"
    #include "ts3_functions.h"
    #include "Aison.h"
    #include <QtWidgets\qinputdialog.h>
    #include <QtCore\qstring.h>
    #include "Input_Dialog.h"
    
    static struct TS3Functions ts3Functions;
    Dialoginput dialog_i;
     
    #ifdef _WIN32
    #define _strcpy(dest, destSize, src) strcpy_s(dest, destSize, src)
    #define snprintf sprintf_s
    #else
    #define _strcpy(dest, destSize, src) { strncpy(dest, src, destSize-1); (dest)[destSize-1] = '\0'; }
    #endif
    I've kept it to pretty basic. I took the basic plugin project from the zip and applied the dialog files.

    Here's the .cpp file for dialog
    Code:
    #include "Input_Dialog.h"
    
    
    Dialoginput::Dialoginput(QWidget *parent) : QDialog(parent)
    {
    	button = new QPushButton("Click Me", this);
    	connect(button, SIGNAL(clicked()), this, SLOT(setText()));
    
    	label = new QLabel(this);
    }
    
    Dialoginput::~Dialoginput()
    {
    	//parent object will destroy its child.
    }
    void Dialoginput::setText()
    {
    	bool ok;
    	QString text = QInputDialog::getText(this, tr("Enter Name"),
    		tr("User name:"), QLineEdit::Normal,
    		"", &ok);
    }
    
    #include "moc_Input_Dialog.cc"
    (It didn't look like this though at first, but when I discovered that it crashes, I kept reverting everything to the very basic to eliminate anything that I might have done, but it didn't work)

  6. #6
    Join Date
    October 2012
    Location
    Germany
    Posts
    553
    Cannot tell about the way you include the moc file (simply because QtCreator does that for me), however what I've experienced is when you instantiate a Qt class at that place, file level, at the very least signal & slots will either not work or might be causing your crash (the connect line in the constructor).

    That's part of the reason I've got those Init functions in the helper singletons and those onRunningStateChanged funcs in the modules, so I can connect later, for example in int ts3plugin_init().

    Might still be "too early" for ui generally, not sure about that.
    I'd try putting the thing in the common plugin configuration scheme to test that out:
    Code:
    int ts3plugin_offersConfigure() {
        return PLUGIN_OFFERS_CONFIGURE_QT_THREAD;
    }
    
    void ts3plugin_configure(void* handle, void* qParentWidget) {
        Q_UNUSED(handle);
    
        Dialoginput* config = new Dialoginput((QWidget*)qParentWidget);
        config->exec();
    }
    Afaict we got one of the few situations here where that pointer becoming inaccessible isn't a problem due to Qt's Delete on Close / parents destroying childs.
    Last edited by Philosound; January 18th, 2015 at 09:07 PM.

  7. #7
    Join Date
    September 2012
    Posts
    6,079
    Quote Originally Posted by Philosound View Post
    Cannot tell about the way you include the moc file (simply because QtCreator does that for me), however what I've experienced is when you instantiate a Qt class at that place, file level, at the very least signal & slots will either not work or might be causing your crash (the connect line in the constructor).

    That's part of the reason I've got those Init functions in the helper singletons and those onRunningStateChanged funcs in the modules, so I can connect later, for example in int ts3plugin_init().

    Might still be "too early" for ui generally, not sure about that.
    Connecting slots and signals within the constructor should work just fine afaik. It's been quite some time since I've used the Qt supplied tools (except for moc, uic) but QtDesigner allows you to specify connections using the UI and iirc uic will translate those to connect calls, not that I've used that much.

    Code:
    myDlg::myDlg(QWidget *parent /*= 0*/) : QDialog(parent) {
    //create Buttons and other UI Objects
    /*QPushButton* */btn = new QPushButton("Do something", this);
    // Connect Signals & Slots
    connect(btn, &QPushButton::clicked, this, &myDlg::onButtonClick);
    }
    Can't remember when it didn't work for me.
    When sending PMs please make sure to include a reference link to the thread in question in the body of your message.

  8. #8
    Join Date
    October 2012
    Location
    Germany
    Posts
    553
    connect within the constructor shouldn't generally be an issue, I use it a lot in there in other apps, plus the Designer should indeed translate it that way. The sole occasion where I had an issue was if said object then gets created on file scope on a TS plugin and by extension the connect call, as opposed to ts3plugin_init or later, where it did work as expected.
    Now, I generally don't tend to do that anyways, so I can't really tell if it's a file scope thing, thread thing, a plugin loader thing, Qt not being fully initialized despite the plugin probably being loaded by QLibrary. I cannot explain that, I just observed it back in the Qt4 days and moved on
    I cannot recall though if it just didn't connect or actually crashed.
    Last edited by Philosound; January 19th, 2015 at 03:25 PM.

  9. #9
    Join Date
    August 2014
    Posts
    27
    Sorry for a late response, I was busy wrapping up uni projects and exams.
    I actually tried what you suggested a couple of days ago already and it worked. I guess you were right about the location of that particular line. I moved it inside the method so the object gets created once it's actually needed and the moment I did it the client no longer crashed and the input dialog appeared when expected. After a bit more additional tweaking I can finally get whatever was inserted and manipulate it how I want.
    I can't thank you enough! I was about to run out of ideas on what to try. I guess that sometimes you just need a second brain to show you or suggest that simple thing that might just fix everything!
    Once again, thanks!

    As for why I'm including the moc file like this: perhaps it wasn't clear, but I'm doing the project in Visual Studio. After Qt "mocs" up the files, this is how I can include them into the compiling process and this is the solution that worked for me.

  10. #10
    Join Date
    September 2012
    Posts
    6,079
    Quote Originally Posted by Birman View Post
    As for why I'm including the moc file like this: perhaps it wasn't clear, but I'm doing the project in Visual Studio. After Qt "mocs" up the files, this is how I can include them into the compiling process and this is the solution that worked for me.
    It's also mentioned like that in the Qt Docs
    Other option would be to actually add the moc'd files to the project without including them anywhere.
    When sending PMs please make sure to include a reference link to the thread in question in the body of your message.

  11. #11
    Join Date
    October 2012
    Location
    Germany
    Posts
    553
    I was just mentioning that to point out my inability to judge the way it's included without looking it up myself

    Glad it worked You know, it's one of those points where plugin development can actually become harder than application development.
    At crashes, the chances of getting useful debug info are slim as the "crown juwels", the debug symbols, are unavailable presumably to slow down reverse engineering attempts. Just saying, crashes can be a real waffle to solve and ate up a lot of time when I started developing my plugin. Luckily, once one is sensible to the moods of the main app, a sense evolves where to bring the chocolates

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. theres got to be a simple way
    By systemshock in forum Server Support
    Replies: 11
    Last Post: December 29th, 2009, 05:10 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •